Exemplo n.º 1
0
        public override void MouseDown(TileMouseState e)
        {
            if (_wvm.SelectedSprite == null)
                return;
            if (_wvm.SelectedSprite.Size.X > 1 || _wvm.SelectedSprite.Size.Y > 1)
            {
                Vector2Short[,] tiles = _wvm.SelectedSprite.GetTiles();
                for (int x = 0; x < _wvm.SelectedSprite.Size.X; x++)
                {
                    int tilex = x + e.Location.X;
                    for (int y = 0; y < _wvm.SelectedSprite.Size.Y; y++)
                    {
                        int tiley = y + e.Location.Y;
                        _wvm.UndoManager.SaveTile(tilex, tiley);
                        Tile curtile = _wvm.CurrentWorld.Tiles[tilex, tiley];
                        curtile.IsActive = true;
                        curtile.Type = _wvm.SelectedSprite.Tile;
                        curtile.U = tiles[x, y].X;
                        curtile.V = tiles[x, y].Y;
                        _wvm.UpdateRenderPixel(tilex, tiley);
                    }
                }
            }
            if (!_isRightDown && !_isLeftDown)
            {
                _startPoint = e.Location;
                _wvm.CheckTiles = new bool[_wvm.CurrentWorld.TilesWide * _wvm.CurrentWorld.TilesHigh];
            }

            _isLeftDown = (e.LeftButton == MouseButtonState.Pressed);
            _isRightDown = (e.RightButton == MouseButtonState.Pressed);

            if (_wvm.SelectedSprite.Size.X == 1 && _wvm.SelectedSprite.Size.Y == 1)
                CheckDirectionandDraw(e.Location);
        }
Exemplo n.º 2
0
        private void DrawLineP2P(Vector2Int32 endPoint)
        {
            foreach (Vector2Int32 pixel in Shape.DrawLineTool(_startPoint, _endPoint))
            {
                if (!_wvm.CurrentWorld.ValidTileLocation(pixel))
                {
                    continue;
                }
                int index = pixel.X + pixel.Y * _wvm.CurrentWorld.TilesWide;
                if (!_wvm.CheckTiles[index])
                {
                    _wvm.CheckTiles[index] = true;
                    if (_wvm.Selection.IsValid(pixel))
                    {
                        if (_wvm.SelectedSprite == null)
                        {
                            return;
                        }

                        Sprite.PlaceSprite(pixel.X, pixel.Y, _wvm.SelectedSprite, _wvm);
                        if (Tile.IsTileEntity(_wvm.SelectedSprite.Tile))
                        {
                            var te = TileEntity.CreateForTile(_wvm.CurrentWorld.Tiles[pixel.X, pixel.Y], pixel.X, pixel.Y, 0);
                            TileEntity.PlaceEntity(te, _wvm);
                        }
                    }
                }
            }
        }
Exemplo n.º 3
0
        private bool BordersAir(Vector2Int32 p)
        {
            int x1 = p.X - 1;

            if (x1 < 0)
            {
                x1 = 0;
            }
            int x2 = p.X + 1;

            if (x2 >= _wvm.CurrentWorld.TilesWide)
            {
                x2 = p.X;
            }
            int y1 = p.Y - 1;

            if (y1 < 0)
            {
                y1 = 0;
            }
            int y2 = p.Y + 1;

            if (y2 >= _wvm.CurrentWorld.TilesHigh)
            {
                y2 = p.X;
            }

            if (!_wvm.CurrentWorld.Tiles[p.X, y1].IsActive || !_wvm.CurrentWorld.Tiles[p.X, y2].IsActive ||
                !_wvm.CurrentWorld.Tiles[x1, p.Y].IsActive || !_wvm.CurrentWorld.Tiles[x2, p.Y].IsActive)
            {
                return(true);
            }
            return(false);
        }
Exemplo n.º 4
0
        public static IEnumerable <Vector2Int32> FillRectangleVectorCenter(Vector2Int32 start, Vector2Int32 end, Vector2Int32 size)
        {
            var offsetStart = new Vector2Int32(start.X - size.X / 2, start.Y - size.Y / 2);
            var offsetEnd   = new Vector2Int32(end.X - size.X / 2, end.Y - size.Y / 2);

            return(FillRectangleVector(offsetStart, offsetEnd, size));
        }
Exemplo n.º 5
0
        private void DrawLineP2P(Vector2Int32 endPoint)
        {
            foreach (Vector2Int32 pixel in Shape.DrawLineTool(_startPoint, _endPoint))
            {
                if (!_wvm.CurrentWorld.ValidTileLocation(pixel))
                {
                    continue;
                }
                int index = pixel.X + pixel.Y * _wvm.CurrentWorld.TilesWide;
                if (!_wvm.CheckTiles[index])
                {
                    _wvm.CheckTiles[index] = true;
                    if (_wvm.Selection.IsValid(pixel))
                    {
                        if (_wvm.SelectedSpriteTile2 == null)
                        {
                            return;
                        }


                        PlaceSelectedSprite(pixel.X, pixel.Y);
                    }
                }
            }
        }
Exemplo n.º 6
0
        private void CheckDirectionandDraw(Vector2Int32 tile)
        {
            Vector2Int32 p = tile;
            Vector2Int32 p2 = tile;
            if (_isRightDown)
            {
                if (_isLeftDown)
                    p.X = _startPoint.X;
                else
                    p.Y = _startPoint.Y;

                DrawLine(p);
                _startPoint = p;
            }
            else if (_isLeftDown)
            {
                if ((Keyboard.IsKeyUp(Key.LeftShift)) && (Keyboard.IsKeyUp(Key.RightShift)))
                {
                    DrawLine(p);
                    _startPoint = p;
                    _endPoint = p;
                }
                else if ((Keyboard.IsKeyDown(Key.LeftShift)) || (Keyboard.IsKeyDown(Key.RightShift)))
                {
                    DrawLineP2P(p2);
                    _endPoint = p2;
                }
            }
        }
Exemplo n.º 7
0
        public override void MouseDown(TileMouseState e)
        {
            if (_wvm.SelectedSprite == null)
            {
                return;
            }

            Sprite.PlaceSprite(e.Location.X, e.Location.Y, _wvm.SelectedSprite, _wvm);
            if (Tile.IsTileEntity(_wvm.SelectedSprite.Tile))
            {
                var te = TileEntity.CreateForTile(_wvm.CurrentWorld.Tiles[e.Location.X, e.Location.Y], e.Location.X, e.Location.Y, 0);
                TileEntity.PlaceEntity(te, _wvm);
            }

            if (!_isRightDown && !_isLeftDown)
            {
                _startPoint     = e.Location;
                _wvm.CheckTiles = new bool[_wvm.CurrentWorld.TilesWide * _wvm.CurrentWorld.TilesHigh];
            }

            _isLeftDown  = (e.LeftButton == MouseButtonState.Pressed);
            _isRightDown = (e.RightButton == MouseButtonState.Pressed);

            if (_wvm.SelectedSprite.Size.X == 1 && _wvm.SelectedSprite.Size.Y == 1)
            {
                CheckDirectionandDraw(e.Location);
            }
        }
Exemplo n.º 8
0
        public void UpdateRadius()
        {
            _Radius -= circleReduce;
            MsgCheckenSceneInfo info = new MsgCheckenSceneInfo();
            var Pos = new Vector2Int32
            {
                x = Utility.MultiplyPrecision(_Center.X),
                y = Utility.MultiplyPrecision(_Center.Y)
            };

            info.CenterPos = Pos;
            info.Radius    = _Radius;
            info.Timer     = 10;
            foreach (var player in EnumAllPlayer())
            {
                if (player.mActive == true)
                {
                    player.Proxy.CK_NotifyCheckenSceneInfo(info);
                }
            }

            if (_Radius <= circleMin)
            {
                DeleteTimer(_triggerRadius);
            }
        }
Exemplo n.º 9
0
        protected void CheckDirectionandDraw(Vector2Int32 tile)
        {
            Vector2Int32 p  = tile;
            Vector2Int32 p2 = tile;

            if (_isRightDown)
            {
                if (_isLeftDown)
                {
                    p.X = _startPoint.X;
                }
                else
                {
                    p.Y = _startPoint.Y;
                }

                DrawLine(p);
                _startPoint = p;
            }
            else if (_isLeftDown)
            {
                if ((Keyboard.IsKeyUp(Key.LeftShift)) && (Keyboard.IsKeyUp(Key.RightShift)))
                {
                    DrawLine(p);
                    _startPoint = p;
                    _endPoint   = p;
                }
                else if ((Keyboard.IsKeyDown(Key.LeftShift)) || (Keyboard.IsKeyDown(Key.RightShift)))
                {
                    DrawLineP2P(p2);
                    _endPoint = p2;
                }
            }
        }
Exemplo n.º 10
0
        public static IEnumerable<Vector2Int32> DrawLine(Vector2Int32 start, Vector2Int32 end)
        {
            // Distance start and end point
            int dx = end.X - start.X;
            int dy = end.Y - start.Y;

            // Determine slope (absoulte value)
            int len = dy >= 0 ? dy : -dy;
            int lenx = dx >= 0 ? dx : -dx;
            if (lenx > len)
            {
                len = lenx;
            }

            // Prevent divison by zero
            if (len != 0)
            {
                // Init steps and start
                float incx = dx / (float)len;
                float incy = dy / (float)len;
                float x = start.X;
                float y = start.Y;

                // Walk the line!
                for (int i = 0; i < len; i++)
                {

                    yield return new Vector2Int32((int)x, (int)y);

                    x += incx;
                    y += incy;
                }
            }
        }
Exemplo n.º 11
0
        public override void MouseDown(TileMouseState e)
        {
            if (_wvm.SelectedSprite2.Value == null)
            {
                return;
            }

            var x = e.Location.X;
            var y = e.Location.Y;

            PlaceSelectedSprite(x, y);

            if (!_isRightDown && !_isLeftDown)
            {
                _startPoint     = e.Location;
                _wvm.CheckTiles = new bool[_wvm.CurrentWorld.TilesWide * _wvm.CurrentWorld.TilesHigh];
            }

            _isLeftDown  = (e.LeftButton == MouseButtonState.Pressed);
            _isRightDown = (e.RightButton == MouseButtonState.Pressed);

            if (_wvm.SelectedSpriteTile2.SizeTiles.X == 1 && _wvm.SelectedSpriteTile2.SizeTiles.Y == 1)
            {
                CheckDirectionandDraw(e.Location);
            }
        }
Exemplo n.º 12
0
        protected void DrawLineP2P(Vector2Int32 endPoint)
        {
            var line = Shape.DrawLineTool(_startPoint, endPoint).ToList();

            if (_wvm.Brush.Shape == BrushShape.Square || _wvm.Brush.Height <= 1 || _wvm.Brush.Width <= 1)
            {
                for (int i = 1; i < line.Count; i++)
                {
                    FillRectangleLine(line[i - 1], line[i]);
                }
            }
            else if (_wvm.Brush.Shape == BrushShape.Round)
            {
                foreach (Vector2Int32 point in line)
                {
                    FillRound(point);
                }
            }
            else if (_wvm.Brush.Shape == BrushShape.Right || _wvm.Brush.Shape == BrushShape.Left)
            {
                foreach (Vector2Int32 point in line)
                {
                    FillSlope(point);
                }
            }
        }
 public HouseGenPluginView()
 {
     InitializeComponent();
     _wvm = null;
     _generatedSchematicSize = new(0, 0);
     HouseGenTemplates       = new List <HouseGenTemplate>();
 }
Exemplo n.º 14
0
        private void CheckDirectionandDraw(Vector2Int32 tile)
        {
            if (_currentBiome != null)
            {
                Vector2Int32 p = tile;
                if (_isRightDown)
                {
                    if (_isLeftDown)
                    {
                        p.X = _startPoint.X;
                    }
                    else
                    {
                        p.Y = _startPoint.Y;
                    }

                    DrawLine(p);
                    _startPoint = p;
                }
                else if (_isLeftDown)
                {
                    DrawLine(p);
                    _startPoint = p;
                }
            }
        }
Exemplo n.º 15
0
        public bool SlopeCheck(Vector2Int32 a, Vector2Int32 b)
        {
            if (a.X < 0 || a.X >= Size.X)
            {
                return(false);
            }
            if (b.X < 0 || b.X >= Size.X)
            {
                return(false);
            }
            if (a.Y < 0 || a.Y >= Size.Y)
            {
                return(false);
            }
            if (b.Y < 0 || b.Y >= Size.Y)
            {
                return(false);
            }

            var ta = Tiles[a.X, a.Y];
            var tb = Tiles[b.X, b.Y];


            var tpa = World.GetTileProperties(ta.Type);
            var tpb = World.GetTileProperties(tb.Type);

            if (ta.IsActive == tb.IsActive && !tpa.IsFramed && !tpb.IsFramed)
            {
                return(true);
            }


            return(false);
        }
Exemplo n.º 16
0
        public static IEnumerable <Vector2Int32> DrawLine(Vector2Int32 start, Vector2Int32 end)
        {
            // Distance start and end point
            int dx = end.X - start.X;
            int dy = end.Y - start.Y;

            // Determine slope (absoulte value)
            int len  = dy >= 0 ? dy : -dy;
            int lenx = dx >= 0 ? dx : -dx;

            if (lenx > len)
            {
                len = lenx;
            }

            // Prevent divison by zero
            if (len != 0)
            {
                // Init steps and start
                float incx = dx / (float)len;
                float incy = dy / (float)len;
                float x    = start.X;
                float y    = start.Y;

                // Walk the line!
                for (int i = 0; i < len; i++)
                {
                    yield return(new Vector2Int32((int)x, (int)y));

                    x += incx;
                    y += incy;
                }
            }
        }
Exemplo n.º 17
0
        public static IEnumerable <Vector2Int32> DrawQuad(Vector2Int32 v1, Vector2Int32 v2, Vector2Int32 v3, Vector2Int32 v4)
        {
            //var result = DrawLine(v1, v2).Concat(DrawLine(v2, v3)).Concat(DrawLine(v3, v4)).Concat(DrawLine(v4, v1));
            //return result; // cannot return concat

            foreach (var vector2Int32 in DrawLine(v1, v2))
            {
                yield return(vector2Int32);
            }

            foreach (var vector2Int32 in DrawLine(v2, v3))
            {
                yield return(vector2Int32);
            }

            foreach (var vector2Int32 in DrawLine(v3, v4))
            {
                yield return(vector2Int32);
            }

            foreach (var vector2Int32 in DrawLine(v4, v1))
            {
                yield return(vector2Int32);
            }
        }
        private Vector2Int32 FlipSprite(Vector2Int32 totalSize, Vector2Int32 vector, Vector2Short size, bool flipX)
        {
            var maxX = totalSize.X - 1;
            var maxY = totalSize.Y - 1;

            int bufferX;
            int bufferY;

            if (flipX)
            {
                bufferX = maxX - vector.X;
                bufferY = vector.Y;

                bufferX -= size.X - 1;
            }
            else
            {
                bufferX = vector.X;
                bufferY = maxY - vector.Y;

                bufferY -= size.Y - 1;
            }

            return(new Vector2Int32(bufferX, bufferY));
        }
Exemplo n.º 19
0
        private void PasteClipboard(Vector2Int32 anchor)
        {
            _wvm.Clipboard.PasteBufferIntoWorld(anchor);
            _wvm.UpdateRenderRegion(new Rectangle(anchor.X, anchor.Y, _wvm.Clipboard.Buffer.Size.X, _wvm.Clipboard.Buffer.Size.Y));

            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, anchor.X, anchor.Y, _wvm.Clipboard.Buffer.Size.X, _wvm.Clipboard.Buffer.Size.Y);
        }
Exemplo n.º 20
0
        private void PasteClipboard(Vector2Int32 anchor)
        {
            _wvm.Clipboard.PasteBufferIntoWorld(anchor);
            _wvm.UpdateRenderRegion(new Rectangle(anchor.X, anchor.Y, _wvm.Clipboard.Buffer.Size.X, _wvm.Clipboard.Buffer.Size.Y));

            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, anchor.X, anchor.Y, _wvm.Clipboard.Buffer.Size.X, _wvm.Clipboard.Buffer.Size.Y);
        }
 public void MouseDown(TileMouseState e)
 {
     if (e.LeftButton == MouseButtonState.Pressed)
         _startSelection = e.Location;
     if (e.RightButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released)
     {
         _wvm.Selection.IsActive = false;
     }
 }
 public static TileMouseState FromHwndMouseEventArgs(HwndMouseEventArgs e, Vector2Int32 tile)
 {
     return new TileMouseState
                {
                    LeftButton = e.LeftButton,
                    RightButton = e.RightButton,
                    MiddleButton = e.MiddleButton,
                    Location = tile
                };
 }
        public void SetRectangle(Vector2Int32 p1, Vector2Int32 p2)
        {
            int x1 = p1.X < p2.X ? p1.X : p2.X;
            int y1 = p1.Y < p2.Y ? p1.Y : p2.Y;
            int width = Math.Abs(p2.X - p1.X) + 1;
            int height = Math.Abs(p2.Y - p1.Y) + 1;

            SelectionArea = new Rectangle(x1, y1, width, height);
            IsActive = true;
        }
Exemplo n.º 24
0
 public static TileMouseState FromHwndMouseEventArgs(HwndMouseEventArgs e, Vector2Int32 tile)
 {
     return(new TileMouseState
     {
         LeftButton = e.LeftButton,
         RightButton = e.RightButton,
         MiddleButton = e.MiddleButton,
         Location = tile
     });
 }
Exemplo n.º 25
0
 public static IEnumerable <Vector2Int32> FillRectangle(Vector2Int32 offset, Vector2Int32 size)
 {
     for (int y = offset.Y; y < offset.Y + size.Y; y++)
     {
         for (int x = offset.X; x < offset.X + size.X; x++)
         {
             yield return(new Vector2Int32(x, y));
         }
     }
 }
Exemplo n.º 26
0
 public static IEnumerable<Vector2Int32> FillRectangle(Vector2Int32 offset, Vector2Int32 size)
 {
     for (int y = offset.Y; y < offset.Y + size.Y; y++)
     {
         for (int x = offset.X; x < offset.X + size.X; x++)
         {
             yield return new Vector2Int32(x, y);
         }
     }
 }
Exemplo n.º 27
0
        public void SetRectangle(Vector2Int32 p1, Vector2Int32 p2)
        {
            int x1     = p1.X < p2.X ? p1.X : p2.X;
            int y1     = p1.Y < p2.Y ? p1.Y : p2.Y;
            int width  = Math.Abs(p2.X - p1.X) + 1;
            int height = Math.Abs(p2.Y - p1.Y) + 1;

            SelectionArea = new Rectangle(x1, y1, width, height);
            IsActive      = true;
        }
 public void MouseDown(TileMouseState e)
 {
     if ((e.LeftButton == MouseButtonState.Pressed) && (Keyboard.IsKeyUp(Key.LeftShift) && Keyboard.IsKeyUp(Key.RightShift)))
         _startSelection = e.Location;
     if ((Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)))
         _modifySelection= e.Location;
     if (e.RightButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released)
         _wvm.Selection.IsActive = false;
     if (e.RightButton == MouseButtonState.Pressed && (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
         _wvm.Selection.IsActive = true;
 }
Exemplo n.º 29
0
 public void MouseDown(TileMouseState e)
 {
     if (e.LeftButton == MouseButtonState.Pressed)
     {
         _startSelection = e.Location;
     }
     if (e.RightButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released)
     {
         _wvm.Selection.IsActive = false;
     }
 }
Exemplo n.º 30
0
        public override void MouseDown(TileMouseState e)
        {
            if (!_isRightDown && !_isLeftDown)
            {
                _startPoint     = e.Location;
                _wvm.CheckTiles = new bool[_wvm.CurrentWorld.TilesWide * _wvm.CurrentWorld.TilesHigh];
            }

            _isLeftDown  = (e.LeftButton == MouseButtonState.Pressed);
            _isRightDown = (e.RightButton == MouseButtonState.Pressed);
            CheckDirectionandDraw(e.Location);
        }
Exemplo n.º 31
0
        public override void MouseDown(TileMouseState e)
        {
            if (!_isRightDown && !_isLeftDown)
            {
                _startPoint = e.Location;
                _wvm.CheckTiles = new bool[_wvm.CurrentWorld.TilesWide * _wvm.CurrentWorld.TilesHigh];
            }

            _isLeftDown = (e.LeftButton == MouseButtonState.Pressed);
            _isRightDown = (e.RightButton == MouseButtonState.Pressed);
            CheckDirectionandDraw(e.Location);
        }
Exemplo n.º 32
0
        public void Flood(Vector2Int32 pt)
        {
            int bitmapWidth  = _wvm.CurrentWorld.TilesWide;
            int bitmapHeight = _wvm.CurrentWorld.TilesHigh;

            int x = pt.X;
            int y = pt.Y;

            _wvm.CheckTiles = new bool[bitmapWidth * bitmapHeight];

            var originTile = (Tile)_wvm.CurrentWorld.Tiles[x, y].Clone();

            LinearFloodFill(ref x, ref y, ref originTile);

            while (_ranges.Count > 0)
            {
                //**Get Next Range Off the Queue
                FloodFillRange range = _ranges.Dequeue();

                //**Check Above and Below Each Pixel in the Floodfill Range
                int downPxIdx = (bitmapWidth * (range.Y + 1)) + range.StartX; //CoordsToPixelIndex(lFillLoc,y+1);
                int upPxIdx   = (bitmapWidth * (range.Y - 1)) + range.StartX; //CoordsToPixelIndex(lFillLoc, y - 1);
                int upY       = range.Y - 1;                                  //so we can pass the y coord by ref
                int downY     = range.Y + 1;
                for (int i = range.StartX; i <= range.EndX; i++)
                {
                    //*Start Fill Upwards
                    //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance
                    if (range.Y > 0 && (!_wvm.CheckTiles[upPxIdx]) && CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[i, upY]) && _wvm.Selection.IsValid(i, upY))
                    {
                        LinearFloodFill(ref i, ref upY, ref originTile);
                    }

                    //*Start Fill Downwards
                    //if we're not below the bottom of the bitmap and the pixel below this one is within the color tolerance
                    if (range.Y < (bitmapHeight - 1) && (!_wvm.CheckTiles[downPxIdx]) && CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[i, downY]) && _wvm.Selection.IsValid(i, downY))
                    {
                        LinearFloodFill(ref i, ref downY, ref originTile);
                    }
                    downPxIdx++;
                    upPxIdx++;
                }

                if (upY < _minY)
                {
                    _minY = upY;
                }
                if (downY > _maxY)
                {
                    _maxY = downY;
                }
            }
        }
Exemplo n.º 33
0
        private BrickStyle?GetBrickStyle(Vector2Int32 v)
        {
            var t  = _wvm.CurrentWorld.Tiles[v.X, v.Y];
            var tp = World.GetTileProperties(t.Type);

            if (!t.IsActive || t.LiquidType != LiquidType.None || tp.IsFramed)
            {
                return(null);
            }

            bool up        = _wvm.CurrentWorld.SlopeCheck(v, new Vector2Int32(v.X, v.Y - 1));
            bool down      = _wvm.CurrentWorld.SlopeCheck(v, new Vector2Int32(v.X, v.Y + 1));
            bool upLeft    = _wvm.CurrentWorld.SlopeCheck(v, new Vector2Int32(v.X - 1, v.Y - 1));
            bool left      = _wvm.CurrentWorld.SlopeCheck(v, new Vector2Int32(v.X - 1, v.Y));
            bool upRight   = _wvm.CurrentWorld.SlopeCheck(v, new Vector2Int32(v.X + 1, v.Y - 1));
            bool right     = _wvm.CurrentWorld.SlopeCheck(v, new Vector2Int32(v.X + 1, v.Y));
            bool downLeft  = _wvm.CurrentWorld.SlopeCheck(v, new Vector2Int32(v.X - 1, v.Y + 1));
            bool downRight = _wvm.CurrentWorld.SlopeCheck(v, new Vector2Int32(v.X + 1, v.Y + 1));

            var mask      = new BitsByte(up, upRight, right, downRight, down, downLeft, left, upLeft);
            var maskValue = mask.Value;

            if (maskValue == byte.MinValue || maskValue == byte.MaxValue)
            {
                return(null);
            }

            if (!up && !down)
            {
                return(null);
            }

            if (!up && left && !right && (downRight || !upRight))
            {
                return(BrickStyle.SlopeTopRight);
            }
            if (!up && right && !left && (downLeft || !upLeft))
            {
                return(BrickStyle.SlopeTopLeft);
            }

            if (!down && left && !right && (!downRight || upRight))
            {
                return(BrickStyle.SlopeBottomRight);
            }
            if (!down && right && !left && (!downLeft || upLeft))
            {
                return(BrickStyle.SlopeBottomLeft);
            }

            return(null);
        }
Exemplo n.º 34
0
        public void Undo()
        {
            if (_currentIndex <= 0)
            {
                return;
            }

            ErrorLogging.TelemetryClient?.TrackEvent(nameof(Undo));


            string     undoFileName = string.Format(UndoFile, _currentIndex - 1); // load previous undo file
            string     redoFileName = string.Format(RedoFile, _currentIndex);     // create redo file at current index
            UndoBuffer redo         = new UndoBuffer(redoFileName);

            Debug.WriteLine($"Opening undo file for undo: {Path.GetFileNameWithoutExtension(undoFileName)}");
            using (var stream = new FileStream(undoFileName, FileMode.Open))
                using (BinaryReader br = new BinaryReader(stream, System.Text.Encoding.UTF8, false))
                {
                    foreach (var undoTile in UndoBuffer.ReadUndoTilesFromStream(br))
                    {
                        Vector2Int32 pixel = undoTile.Location;
                        SaveTileToBuffer(redo, pixel.X, pixel.Y, true);
                        _wvm.CurrentWorld.Tiles[pixel.X, pixel.Y] = (Tile)undoTile.Tile;
                        _wvm.UpdateRenderPixel(pixel);

                        /* Heathtech */
                        BlendRules.ResetUVCache(_wvm, pixel.X, pixel.Y, 1, 1);
                    }

                    redo.Close();
                    redo.Dispose();
                    redo = null;

                    foreach (var chest in World.LoadChestData(br))
                    {
                        _wvm.CurrentWorld.Chests.Add(chest);
                    }
                    foreach (var sign in World.LoadSignData(br))
                    {
                        _wvm.CurrentWorld.Signs.Add(sign);
                    }
                    foreach (var te in World.LoadTileEntityData(br, World.CompatibleVersion))
                    {
                        _wvm.CurrentWorld.TileEntities.Add(te);
                    }
                }

            _currentIndex--; // move index back one, create a new buffer
            CreateBuffer();
            //_wvm.CurrentWorld.UpgradeLegacyTileEntities();
            OnUndid(this, EventArgs.Empty);
        }
Exemplo n.º 35
0
        public bool ValidTileLocation(Vector2Int32 point)
        {
            if (point.X < 0)
                return false;
            if (point.Y < 0)
                return false;
            if (point.Y >= _tilesHigh)
                return false;
            if (point.X >= _tilesWide)
                return false;

            return true;
        }
Exemplo n.º 36
0
 private void DrawLineP2P(Vector2Int32 endPoint)
 {
     foreach (Vector2Int32 point in Shape.DrawLineTool(_startPoint, _endPoint))
     {
         if (_wvm.Brush.Shape == BrushShape.Square || _wvm.Brush.Height <= 1 || _wvm.Brush.Width <= 1)
         {
             FillRectangle(point);
         }
         else if (_wvm.Brush.Shape == BrushShape.Round)
         {
             FillRound(point);
         }
     }
 }
Exemplo n.º 37
0
        private void MorphTile(Vector2Int32 p)
        {
            var curtile = _wvm.CurrentWorld.Tiles[p.X, p.Y];

            if (curtile.IsActive)
            {
                foreach (var biome in Biomes)
                {
                    if ((curtile.Type == biome.Stone || ((curtile.Type == biome.Dirt || curtile.Type == biome.Grass) && _currentBiome.DirtToStone)) && !_currentBiome.StoneToDirt)
                    {
                        curtile.Type = _currentBiome.Stone;
                    }
                    else if ((curtile.Type == biome.Dirt || (curtile.Type == biome.Sand && _currentBiome.SandToDirt) || (curtile.Type == biome.Stone && _currentBiome.StoneToDirt)) && !_currentBiome.DirtToSand)
                    {
                        if (BordersAir(p))
                        {
                            curtile.Type = _currentBiome.Grass;
                        }
                        else
                        {
                            curtile.Type = _currentBiome.Dirt;
                        }
                    }
                    else if (curtile.Type == biome.Grass)
                    {
                        curtile.Type = _currentBiome.Grass;
                    }
                    else if (curtile.Type == biome.Sand || ((curtile.Type == biome.Dirt || curtile.Type == biome.Grass) && _currentBiome.DirtToSand))
                    {
                        curtile.Type = _currentBiome.Sand;
                    }
                    else if (curtile.Type == biome.Vines)
                    {
                        curtile.Type = _currentBiome.Vines;
                    }
                    else if (curtile.Type == biome.Plant)
                    {
                        curtile.Type = _currentBiome.Plant;
                    }
                    else if (curtile.Type == biome.Tree)
                    {
                        curtile.Type = _currentBiome.Tree;
                    }
                }
            }
            if (curtile.Wall == 1 || curtile.Wall == 2 || curtile.Wall == 3 || curtile.Wall == 15 || curtile.Wall == 16 || curtile.Wall == 28)
            {
                curtile.Wall = _currentBiome.Wall;
            }
        }
Exemplo n.º 38
0
        public override void MouseDown(TileMouseState e)
        {
            if (!_isRightDown && !_isLeftDown)
            {
                _startPoint = e.Location;
                System.Diagnostics.Debug.WriteLine($"Update _startpoint {_startPoint} MouseDown");

                _wvm.CheckTiles = new bool[_wvm.CurrentWorld.TilesWide * _wvm.CurrentWorld.TilesHigh];
            }

            _isLeftDown  = (e.LeftButton == MouseButtonState.Pressed);
            _isRightDown = (e.RightButton == MouseButtonState.Pressed);
            CheckDirectionandDraw(e.Location);
        }
        //tileStart and tileEnd use the "A1" notation based on the pictoral representation of tiles in http://seancode.com/terrafirma/uvs.html
        //Note that http://seancode.com/terrafirma/uvs.html does not list "N" as a possible row, but the rules used here do (and have been adjusted accordingly)
        private void SetUVsForString(string tileStart, string tileEnd)
        {
            uvPos = new Vector2Int32[3];
            int y1 = tileStart[0] - 'A';
            int x1 = Convert.ToInt32(tileStart.Substring(1)) - 1;
            int y2 = tileEnd[0] - 'A';
            int x2 = Convert.ToInt32(tileEnd.Substring(1)) - 1;
            int y3 = y2 - (y2 - y1) / 2;
            int x3 = x2 - (x2 - x1) / 2;

            uvPos[0] = new Vector2Int32(x1, y1);
            uvPos[1] = new Vector2Int32(x3, y3);
            uvPos[2] = new Vector2Int32(x2, y2);
        }
Exemplo n.º 40
0
 private bool BordersAir(Vector2Int32 p)
 {
     for (int y = -1; y <= 1; y++)
     {
         for (int x = -1; x <= 1; x++)
         {
             if (!_wvm.CurrentWorld.Tiles[p.X + x, p.Y + y].IsActive)
             {
                 return(true);
             }
         }
     }
     return(false);
 }
Exemplo n.º 41
0
        public static IEnumerable<Vector2Int32> FillEllipse(Vector2Int32 offset, Vector2Int32 size)
        {
            // Calc center and radius
            int xr = (size.X - offset.X) >> 1;
            int yr = (size.Y - offset.Y) >> 1;
            int xc = offset.X + xr;
            int yc = offset.Y + yr;

            var center = new Vector2Int32(xc, yc);
            var radius = new Vector2Int32(xr, yr);

            Debug.WriteLine(string.Format("Center: {0}, Radius: {1}", center, radius));

            return FillEllipseCentered(center, radius);
        }
Exemplo n.º 42
0
        public override void MouseDown(TileMouseState e)
        {
            if (!_isRightDown && !_isLeftDown)
            {
                _currentBiome = Biomes.FirstOrDefault(b=>b.Biome== _wvm.MorphBiomeTarget);
                _startPoint = e.Location;
                _dirtLayer = (int)_wvm.CurrentWorld.GroundLevel;
                _rockLayer = (int)_wvm.CurrentWorld.RockLevel;
                _wvm.CheckTiles = new bool[_wvm.CurrentWorld.TilesWide * _wvm.CurrentWorld.TilesHigh];
            }

            _isLeftDown = (e.LeftButton == MouseButtonState.Pressed);
            _isRightDown = (e.RightButton == MouseButtonState.Pressed);
            CheckDirectionandDraw(e.Location);
        }
Exemplo n.º 43
0
        private void DrawLine(Vector2Int32 to)
        {
            foreach (Vector2Int32 pixel in Shape.DrawLineTool(_startPoint, to))
            {
                if (!_wvm.CurrentWorld.ValidTileLocation(pixel)) continue;

                int index = pixel.X + pixel.Y * _wvm.CurrentWorld.TilesWide;
                if (!_wvm.CheckTiles[index])
                {
                    _wvm.CheckTiles[index] = true;
                    if (_wvm.Selection.IsValid(pixel))
                    {
                        _wvm.UndoManager.SaveTile(pixel);
                        _wvm.SetPixel(pixel.X, pixel.Y);
                    }
                }
            }
        }
Exemplo n.º 44
0
        private void CheckDirectionandDraw(Vector2Int32 tile)
        {
            Vector2Int32 p = tile;
            if (_isRightDown)
            {
                if (_isLeftDown)
                    p.X = _startPoint.X;
                else
                    p.Y = _startPoint.Y;

                DrawLine(p);
                _startPoint = p;
            }
            else if (_isLeftDown)
            {
                DrawLine(p);
                _startPoint = p;
            }
        }
Exemplo n.º 45
0
        public void Add(Vector2Int32 location, Tile tile)
        {
            var undoTile = new UndoTile(location, tile);

            if (undoTile == null)
            {
                throw new Exception("Null undo?");
            }

            lock (UndoSaveLock)
            {
                UndoTiles.Add(undoTile);
                LastTile = undoTile;
            }
            if (UndoTiles.Count > FlushSize)
            {
                Flush();
            }
        }
Exemplo n.º 46
0
        public void Flood(Vector2Int32 pt)
        {
            int bitmapWidth = _wvm.CurrentWorld.TilesWide;
            int bitmapHeight = _wvm.CurrentWorld.TilesHigh;

            int x = pt.X;
            int y = pt.Y;
            _wvm.CheckTiles = new bool[bitmapWidth * bitmapHeight];

            var originTile = (Tile)_wvm.CurrentWorld.Tiles[x, y].Clone();
            LinearFloodFill(ref x, ref y, ref originTile);

            while (_ranges.Count > 0)
            {
                //**Get Next Range Off the Queue
                FloodFillRange range = _ranges.Dequeue();

                //**Check Above and Below Each Pixel in the Floodfill Range
                int downPxIdx = (bitmapWidth * (range.Y + 1)) + range.StartX;//CoordsToPixelIndex(lFillLoc,y+1);
                int upPxIdx = (bitmapWidth * (range.Y - 1)) + range.StartX;//CoordsToPixelIndex(lFillLoc, y - 1);
                int upY = range.Y - 1;//so we can pass the y coord by ref
                int downY = range.Y + 1;
                for (int i = range.StartX; i <= range.EndX; i++)
                {
                    //*Start Fill Upwards
                    //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance
                    if (range.Y > 0 && (!_wvm.CheckTiles[upPxIdx]) && CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[i, upY]) && _wvm.Selection.IsValid(i, upY))
                        LinearFloodFill(ref i, ref upY, ref originTile);

                    //*Start Fill Downwards
                    //if we're not below the bottom of the bitmap and the pixel below this one is within the color tolerance
                    if (range.Y < (bitmapHeight - 1) && (!_wvm.CheckTiles[downPxIdx]) && CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[i, downY]) && _wvm.Selection.IsValid(i, downY))
                        LinearFloodFill(ref i, ref downY, ref originTile);
                    downPxIdx++;
                    upPxIdx++;
                }

                if (upY < _minY)
                    _minY = upY;
                if (downY > _maxY)
                    _maxY = downY;
            }
        }
 private void AddNpc(int npcId)
 {
     if (CurrentWorld != null && World.NpcNames.ContainsKey(npcId))
     {
         string name = World.NpcNames[npcId];
         if (CurrentWorld.NPCs.All(n => n.SpriteId != npcId))
         {
             var spawn = new Vector2Int32(CurrentWorld.SpawnX, CurrentWorld.SpawnY);
             CurrentWorld.NPCs.Add(new NPC{Home = spawn, IsHomeless = true, DisplayName = name, Name = name, Position= new Vector2(spawn.X * 16, spawn.Y * 16), SpriteId = npcId});
             Points.Add(name);
             MessageBox.Show(string.Format("{0} added to spawn.", name), "NPC Added");
         }
         else
         {
             MessageBox.Show(string.Format("{0} is already on the map.", name), "NPC Exists");
         }
     }
     else
     {
         MessageBox.Show(string.Format("Choose an NPC. NPC {0} not found.", npcId), "NPC Error");
     }
 }
 private Vector2Int32 TrackUV(int num)
 {
     var uv = new Vector2Int32(0, 0);
     switch (num)
     {
         case 0: uv.X = 0; uv.Y = 0; break;
         case 1: uv.X = 1; uv.Y = 0; break;
         case 2: uv.X = 2; uv.Y = 1; break;
         case 3: uv.X = 3; uv.Y = 1; break;
         case 4: uv.X = 0; uv.Y = 2; break;
         case 5: uv.X = 1; uv.Y = 2; break;
         case 6: uv.X = 0; uv.Y = 1; break;
         case 7: uv.X = 1; uv.Y = 1; break;
         case 8: uv.X = 0; uv.Y = 3; break;
         case 9: uv.X = 1; uv.Y = 3; break;
         case 10: uv.X = 4; uv.Y = 1; break;
         case 11: uv.X = 5; uv.Y = 1; break;
         case 12: uv.X = 6; uv.Y = 1; break;
         case 13: uv.X = 7; uv.Y = 1; break;
         case 14: uv.X = 2; uv.Y = 0; break;
         case 15: uv.X = 3; uv.Y = 0; break;
         case 16: uv.X = 4; uv.Y = 0; break;
         case 17: uv.X = 5; uv.Y = 0; break;
         case 18: uv.X = 6; uv.Y = 0; break;
         case 19: uv.X = 7; uv.Y = 0; break;
         case 20: uv.X = 0; uv.Y = 4; break;
         case 21: uv.X = 1; uv.Y = 4; break;
         case 22: uv.X = 0; uv.Y = 5; break;
         case 23: uv.X = 1; uv.Y = 5; break;
         case 24: uv.X = 2; uv.Y = 2; break;
         case 25: uv.X = 3; uv.Y = 2; break;
         case 26: uv.X = 4; uv.Y = 2; break;
         case 27: uv.X = 5; uv.Y = 2; break;
         case 28: uv.X = 6; uv.Y = 2; break;
         case 29: uv.X = 7; uv.Y = 2; break;
         case 30: uv.X = 2; uv.Y = 3; break;
         case 31: uv.X = 3; uv.Y = 3; break;
         case 32: uv.X = 4; uv.Y = 3; break;
         case 33: uv.X = 5; uv.Y = 3; break;
         case 34: uv.X = 6; uv.Y = 3; break;
         case 35: uv.X = 7; uv.Y = 3; break;
         case 36: uv.X = 0; uv.Y = 6; break;
         case 37: uv.X = 1; uv.Y = 6; break;
         case 38: uv.X = 0; uv.Y = 7; break;
         case 39: uv.X = 1; uv.Y = 7; break;
     }
     return uv;
 }
Exemplo n.º 49
0
 public static IEnumerable<Vector2Int32> FillTriangle(Vector2Int32 v1, Vector2Int32 v2, Vector2Int32 v3)
 {
     return FillPolygon(new[] { v1, v2, v3 });
 }
        /* Heathtech */
        //Pretty much overwrote this whole function.  The original part is still intact, but much more hidden
        private void DrawSprites()
        {
            Rectangle visibleBounds = GetViewingArea();
            TEditXna.Terraria.Objects.BlendRules blendRules = TEditXna.Terraria.Objects.BlendRules.Instance;
            var width  = _wvm.CurrentWorld.TilesWide;
            var height = _wvm.CurrentWorld.TilesHigh;


            if (visibleBounds.Height * visibleBounds.Width < 25000)
            {
                //Extended the viewing space to give tiles time to cache their UV's
                for (int y = visibleBounds.Top - 1; y < visibleBounds.Bottom + 2; y++)
                {
                    for (int x = visibleBounds.Left - 1; x < visibleBounds.Right + 2; x++)
                    {
                        if (x < 0 || y < 0 || x >= _wvm.CurrentWorld.TilesWide || y >= _wvm.CurrentWorld.TilesHigh)
                        {
                            continue;
                        }

                        var curtile = _wvm.CurrentWorld.Tiles[x, y];
                        var tileprop = World.TileProperties[curtile.Type];

                        //Neighbor tiles are often used when dynamically determining which UV position to render
                        int e = 0, n = 1, w = 2, s = 3, ne = 4, nw = 5, sw = 6, se = 7;
                        Tile[] neighborTile = new Tile[8];
                        neighborTile[ e] = (x + 1) < width                     ? _wvm.CurrentWorld.Tiles[x + 1, y    ] : null;
                        neighborTile[ n] = (y - 1) > 0                         ? _wvm.CurrentWorld.Tiles[x    , y - 1] : null;
                        neighborTile[ w] = (x - 1) > 0                         ? _wvm.CurrentWorld.Tiles[x - 1, y    ] : null;
                        neighborTile[ s] = (y + 1) < height                    ? _wvm.CurrentWorld.Tiles[x    , y + 1] : null;
                        neighborTile[ne] = (x + 1) < width && (y - 1) > 0      ? _wvm.CurrentWorld.Tiles[x + 1, y - 1] : null;
                        neighborTile[nw] = (x - 1) > 0     && (y - 1) > 0      ? _wvm.CurrentWorld.Tiles[x - 1, y - 1] : null;
                        neighborTile[sw] = (x - 1) > 0     && (y + 1) < height ? _wvm.CurrentWorld.Tiles[x - 1, y + 1] : null;
                        neighborTile[se] = (x + 1) < width && (y + 1) < height ? _wvm.CurrentWorld.Tiles[x + 1, y + 1] : null;

                        //draw background textures
                        if (y >= 80)
                        {
                            int[,] backstyle = {
                                {66, 67, 68, 69, 128, 125, 185},
                                {70, 71, 68, 72, 128, 125, 185},
                                {73, 74, 75, 76, 134, 125, 185},
                                {77, 78, 79, 82, 134, 125, 185},
                                {83, 84, 85, 86, 137, 125, 185},
                                {83, 87, 88, 89, 137, 125, 185},
                                {121, 122, 123, 124, 140, 125, 185},
                                {153, 147, 148, 149, 150, 125, 185},
                                {146, 154, 155, 156, 157, 125, 185}
                            };
                            int hellback = _wvm.CurrentWorld.HellBackStyle;
                            int backX = 0;
                            if (x <= _wvm.CurrentWorld.CaveBackX0)
                                backX = _wvm.CurrentWorld.CaveBackStyle0;
                            else if (x > _wvm.CurrentWorld.CaveBackX0 && x <= _wvm.CurrentWorld.CaveBackX1)
                                backX = _wvm.CurrentWorld.CaveBackStyle1;
                            else if (x > _wvm.CurrentWorld.CaveBackX1 && x <= _wvm.CurrentWorld.CaveBackX2)
                                backX = _wvm.CurrentWorld.CaveBackStyle2;
                            else if (x > _wvm.CurrentWorld.CaveBackX2)
                                backX = _wvm.CurrentWorld.CaveBackStyle3;
                            var source = new Rectangle(0, 0, 16, 16);
                            var backTex = _textureDictionary.GetBackground(0);
                            if (y < _wvm.CurrentWorld.GroundLevel)
                            {
                                backTex = _textureDictionary.GetBackground(0);
                                source.Y += (y - 80) * 16;
                            }
                            else if (y == _wvm.CurrentWorld.GroundLevel)
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 0]);
                                source.X += (x % 8) * 16;
                            }
                            else if (y > _wvm.CurrentWorld.GroundLevel && y < _wvm.CurrentWorld.RockLevel)
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 1]);
                                source.X += (x % 8) * 16;
                                source.Y += ((y - 1 - (int)_wvm.CurrentWorld.GroundLevel) % 6) * 16;
                            }
                            else if (y == _wvm.CurrentWorld.RockLevel)
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 2]);
                                source.X += (x % 8) * 16;
                            }
                            else if (y > _wvm.CurrentWorld.RockLevel && y < (_wvm.CurrentWorld.TilesHigh - 327))
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 3]);
                                source.X += (x % 8) * 16;
                                source.Y += ((y - 1 - (int)_wvm.CurrentWorld.RockLevel) % 6) * 16;
                            }
                            else if (y == (_wvm.CurrentWorld.TilesHigh - 327))
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 4] + hellback);
                                source.X += (x % 8) * 16;
                            }
                            else if (y > (_wvm.CurrentWorld.TilesHigh - 327) && y < (_wvm.CurrentWorld.TilesHigh - 200))
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 5] + hellback);
                                source.X += (x % 8) * 16;
                                source.Y += ((y - 1 - (int)_wvm.CurrentWorld.TilesHigh + 327) % 18) * 16;
                            }
                            else if (y == (_wvm.CurrentWorld.TilesHigh - 200))
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 6] + hellback);
                                source.X += (x % 8) * 16;
                            }
                            else
                            {
                                backTex = _textureDictionary.GetUnderworld(4);
                                source.Y += (y - (int)_wvm.CurrentWorld.TilesHigh + 200) * 16;
                            }

                            var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                            _spriteBatch.Draw(backTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileBackgroundTextures);
                        }

                        if (_wvm.ShowWalls)
                        {
                            if (curtile.Wall > 0)
                            {
                                var wallTex = _textureDictionary.GetWall(curtile.Wall);

                                if (wallTex != null)
                                {
                                    if (curtile.uvWallCache == 0xFFFF)
                                    {
                                        int sameStyle = 0x00000000;
                                        sameStyle |= (neighborTile[e] != null && neighborTile[e].Wall > 0) ? 0x0001 : 0x0000;
                                        sameStyle |= (neighborTile[n] != null && neighborTile[n].Wall > 0) ? 0x0010 : 0x0000;
                                        sameStyle |= (neighborTile[w] != null && neighborTile[w].Wall > 0) ? 0x0100 : 0x0000;
                                        sameStyle |= (neighborTile[s] != null && neighborTile[s].Wall > 0) ? 0x1000 : 0x0000;

                                        Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, 0x00000000, 0);
                                        curtile.uvWallCache = (ushort)((uvBlend.Y << 8) + uvBlend.X);
                                    }

                                    var texsize = new Vector2Int32(32, 32);
                                    var source = new Rectangle((curtile.uvWallCache & 0x00FF) * (texsize.X + 4), (curtile.uvWallCache >> 8) * (texsize.Y + 4), texsize.X, texsize.Y);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x - 0.5) * _zoom), 1 + (int)((_scrollPosition.Y + y - 0.5) * _zoom), (int)_zoom * 2, (int)_zoom * 2);

                                    _spriteBatch.Draw(wallTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileWallTextures);
                                }
                            }
                        }
                        if (_wvm.ShowTiles)
                        {
                            if (curtile.IsActive)
                            {
                                if (tileprop.IsFramed)
                                {
                                    Rectangle source = new Rectangle(), dest = new Rectangle();
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    bool isTreeSpecial = false, isMushroom = false;
                                    bool isLeft = false, isBase = false, isRight = false;
                                    if (curtile.Type == (int)TileType.Tree)
                                    {
                                        int baseX = 0;
                                        if (curtile.U == 66 && curtile.V <= 45)
                                            ++baseX;
                                        if (curtile.U == 88 && curtile.V >= 66 && curtile.V <= 110)
                                            --baseX;
                                        if (curtile.U == 22 && curtile.V >= 132 && curtile.V < 198)
                                            --baseX;
                                        if (curtile.U == 44 && curtile.V >= 132 && curtile.V < 198)
                                            ++baseX;
                                        if (curtile.U >= 22 && curtile.V >= 198)
                                        {
                                            isTreeSpecial = true;
                                            switch (curtile.U)
                                            {
                                                case 22: isBase = true; break;
                                                case 44: isLeft = true; ++baseX; break;
                                                case 66: isRight = true; --baseX; break;
                                            }
                                        }

                                        //Check tree type
                                        int treeType = -1; //Default to normal in case no grass grows beneath the tree
                                        for (int i = 0; i < 100; i++)
                                        {
                                            Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null;
                                            if (checkTile != null && checkTile.IsActive)
                                            {
                                                bool found = true;
                                                switch (checkTile.Type)
                                                {
                                                    case 2: treeType = -1; break; //Normal
                                                    case 23: treeType = 0; break; //Corruption
                                                    case 60:
                                                        if (y <= _wvm.CurrentWorld.GroundLevel)
                                                        {
                                                            treeType = 1; break; // Jungle
                                                        }
                                                        treeType = 5; break; // Underground Jungle
                                                    case 70: treeType = 6; break; // Surface Mushroom
                                                    case 109: treeType = 2; break; // Hallow
                                                    case 147: treeType = 3; break; // Snow
                                                    case 199: treeType = 4; break; // Crimson
                                                    default: found = false; break;
                                                }
                                                if (found)
                                                    break;
                                            }
                                        }
                                        if (isTreeSpecial)
                                        {
                                            int treeStyle = 0; // default branches and tops
                                            switch (treeType)
                                            {
                                                case -1:
                                                    if (x <= _wvm.CurrentWorld.TreeX0)
                                                        treeStyle = _wvm.CurrentWorld.TreeStyle0;
                                                    else if (x <= _wvm.CurrentWorld.TreeX1)
                                                        treeStyle = _wvm.CurrentWorld.TreeStyle1;
                                                    else if (x <= _wvm.CurrentWorld.TreeX2)
                                                        treeStyle = _wvm.CurrentWorld.TreeStyle2;
                                                    else
                                                        treeStyle = _wvm.CurrentWorld.TreeStyle3;
                                                    if (treeStyle == 0)
                                                    {
                                                        break;
                                                    }
                                                    if (treeStyle == 5)
                                                    {
                                                        treeStyle = 10; break;
                                                    }
                                                    treeStyle = 5 + treeStyle; break;
                                                case 0:
                                                    treeStyle = 1; break;
                                                case 1:
                                                    treeStyle = 2;
                                                    if (_wvm.CurrentWorld.BgJungle == 1)
                                                        treeStyle = 11;
                                                    break;
                                                case 2:
                                                    treeStyle = 3; break;
                                                case 3:
                                                    treeStyle = 4;
                                                    if (_wvm.CurrentWorld.BgSnow == 0)
                                                    {
                                                        treeStyle = 12;
                                                        if (x % 10 == 0)
                                                            treeStyle = 18;
                                                    }
                                                    if (_wvm.CurrentWorld.BgSnow != 2 && _wvm.CurrentWorld.BgSnow != 3 && _wvm.CurrentWorld.BgSnow != 32 && _wvm.CurrentWorld.BgSnow != 4 && _wvm.CurrentWorld.BgSnow != 42)
                                                    {
                                                        break;
                                                    }
                                                    if (_wvm.CurrentWorld.BgSnow % 2 == 0)
                                                    {
                                                        if (x < _wvm.CurrentWorld.TilesWide / 2)
                                                        {
                                                            treeStyle = 16; break;
                                                        }
                                                        treeStyle = 17; break;
                                                    }
                                                    else
                                                    {
                                                        if (x > _wvm.CurrentWorld.TilesWide / 2)
                                                        {
                                                            treeStyle = 16; break;
                                                        }
                                                        treeStyle = 17; break;
                                                    }
                                                case 4:
                                                    treeStyle = 5; break;
                                                case 5:
                                                    treeStyle = 13; break;
                                                case 6:
                                                    treeStyle = 14; break;
                                            }
                                            //Abuse uvTileCache to remember what type of tree it is, since potentially scanning a hundred of blocks PER tree tile sounds slow
                                            curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeStyle);
                                            if (isBase)
                                            {
                                                tileTex = (Texture2D)_textureDictionary.GetTreeTops(treeStyle);
                                            }
                                            else
                                            {
                                                tileTex = (Texture2D)_textureDictionary.GetTreeBranches(treeStyle);
                                            }
                                        }
                                        else
                                        {
                                            tileTex = _textureDictionary.GetTree(treeType);
                                        }
                                    }
                                    if (curtile.Type == (int)TileType.MushroomTree && curtile.U >= 36)
                                    {
                                        isMushroom = true;
                                        tileTex = (Texture2D)_textureDictionary.GetShroomTop(0);
                                    }
                                    if (curtile.Type == 323)
                                    {
                                        if (curtile.U >= 88 && curtile.U <= 132)
                                        {
                                            isTreeSpecial = true;
                                            isBase = true;
                                            tileTex = (Texture2D)_textureDictionary.GetTreeTops(15);
                                        }
                                        int treeType = 0;
                                        for (int i = 0; i < 100; i++)
                                        {
                                            Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + i] : null;
                                            if (checkTile != null && checkTile.IsActive)
                                            {
                                                bool found = true;
                                                switch (checkTile.Type)
                                                {
                                                    case 53: treeType = 0; break; //Palm
                                                    case 112: treeType = 3; break; //Ebonsand Palm
                                                    case 116: treeType = 2; break; //Pearlsand Palm
                                                    case 234: treeType = 1; break; //Crimsand Palm
                                                    default: found = false; break;
                                                }
                                                if (found)
                                                    break;
                                            }
                                        }
                                        curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeType);
                                    }

                                    if (tileTex != null)
                                    {
                                        if ((curtile.Type == 128 || curtile.Type == 269) && curtile.U >= 100)
                                        {
                                            int armor = curtile.U / 100;
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            switch (curtile.V / 18)
                                            {
                                                case 0:
                                                    tileTex = (Texture2D)_textureDictionary.GetArmorHead(armor);
                                                    source = new Rectangle (2, 0, 36, 36);
                                                    dest.Width = (int)(_zoom * source.Width / 16f);
                                                    dest.Height = (int)(_zoom * source.Height / 16f);
                                                    dest.Y += (int)(((16 - source.Height - 4) / 2F) * _zoom / 16);
                                                    dest.X -= (int)((2 * _zoom / 16));
                                                    break;
                                                case 1:
                                                    if (curtile.Type == 128)
                                                        tileTex = (Texture2D)_textureDictionary.GetArmorBody(armor);
                                                    else
                                                        tileTex = (Texture2D)_textureDictionary.GetArmorFemale(armor);
                                                    source = new Rectangle (2, 0, 36, 54);
                                                    dest.Width = (int)(_zoom * source.Width / 16f);
                                                    dest.Height = (int)(_zoom * source.Height / 16f);
                                                    dest.Y += (int)(((16 - source.Height - 18) / 2F) * _zoom / 16);
                                                    dest.X -= (int)((2 * _zoom / 16));
                                                    break;
                                                case 2:
                                                    tileTex = (Texture2D)_textureDictionary.GetArmorLegs(armor);
                                                    source = new Rectangle (2, 42, 36, 12);
                                                    dest.Width = (int)(_zoom * source.Width / 16f);
                                                    dest.Height = (int)(_zoom * source.Height / 16f);
                                                    dest.Y -= (int)((2 * _zoom / 16));
                                                    dest.X -= (int)((2 * _zoom / 16));
                                                    break;
                                            }
                                            if (curtile.U % 100 < 36)
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.FlipHorizontally, LayerTileTrack);
                                            else
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                            tileTex = _textureDictionary.GetTile(curtile.Type);
                                            source = new Rectangle((curtile.U % 100), curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                        }
                                        else if (curtile.Type == 334 && curtile.U >= 5000)
                                        {
                                            if (_wvm.CurrentWorld.Tiles[x + 1, y].U >= 5000)
                                            {
                                                int weapon = (curtile.U % 5000) - 100;
                                                tileTex = (Texture2D)_textureDictionary.GetItem(weapon);
                                                int flip = curtile.U / 5000;
                                                float scale = 1f;
                                                if (tileTex.Width > 40 || tileTex.Height > 40)
                                                {
                                                    if (tileTex.Width > tileTex.Height)
                                                        scale = 40f / (float)tileTex.Width;
                                                    else
                                                        scale = 40f / (float)tileTex.Height;
                                                }
                                                scale *= World.ItemProperties[weapon].Scale;
                                                source = new Rectangle(0, 0, tileTex.Width, tileTex.Height);
                                                SpriteEffects effect = SpriteEffects.None;
                                                if (flip >= 3)
                                                {
                                                    effect = SpriteEffects.FlipHorizontally;
                                                }
                                                _spriteBatch.Draw(tileTex, new Vector2(1 + (int)((_scrollPosition.X + x + 1.5) * _zoom) , 1 + (int)((_scrollPosition.Y + y + .5) * _zoom)), source, Color.White, 0f, new Vector2((float)(tileTex.Width / 2), (float)(tileTex.Height / 2)), scale * _zoom / 16f, effect, LayerTileTrack);
                                            }
                                            source = new Rectangle(((curtile.U / 5000) - 1) * 18, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            tileTex = _textureDictionary.GetTile(curtile.Type);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                        }
                                        else if (curtile.Type == 395 && curtile.V == 0 && curtile.U % 36 == 0)
                                        {
                                            TileEntity entity = _wvm.CurrentWorld.GetTileEntityAtTile(x, y);
                                            if (entity != null)
                                            {
                                                int item = entity.NetId;
                                                if (item > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetItem(item);
                                                    float scale = 1f;
                                                    if (tileTex.Width > 20 || tileTex.Height > 20)
                                                    {
                                                        if (tileTex.Width > tileTex.Height)
                                                            scale = 20f / (float)tileTex.Width;
                                                        else
                                                            scale = 20f / (float)tileTex.Height;
                                                    }
                                                    scale *= World.ItemProperties[item].Scale;
                                                    source = new Rectangle(0, 0, tileTex.Width, tileTex.Height);
                                                    _spriteBatch.Draw(tileTex, new Vector2(1 + (int)((_scrollPosition.X + x + 1) * _zoom) , 1 + (int)((_scrollPosition.Y + y + 1) * _zoom)), source, Color.White, 0f, new Vector2((float)(tileTex.Width / 2), (float)(tileTex.Height / 2)), scale * _zoom / 16f, SpriteEffects.FlipHorizontally, LayerTileTrack);
                                                }
                                            }
                                            source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            tileTex = _textureDictionary.GetTile(curtile.Type);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                        }
                                        else if (curtile.Type == 171) // Christmas Tree
                                        {
                                            if (curtile.U >= 10)
                                            {
                                                int star = curtile.V & 7;
                                                int garland = (curtile.V >> 3) & 7;
                                                int bulb = (curtile.V >> 6) & 0xf;
                                                int light = (curtile.V >> 10) & 0xf;
                                                source = new Rectangle(0, 0, 64, 128);
                                                dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom * 4, (int)_zoom * 8);
                                                if (star > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_3");
                                                    source.X = 66 * (star - 1);
                                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                                }
                                                if (garland > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_1");
                                                    source.X = 66 * (garland - 1);
                                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                                }
                                                if (bulb > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_2");
                                                    source.X = 66 * (bulb - 1);
                                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                                }
                                                if (light > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_4");
                                                    source.X = 66 * (light - 1);
                                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                                }
                                                source.X = 0;
                                                tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_0");
                                            }
                                        }
                                        else if (curtile.Type == 314)
                                        {
                                            source = new Rectangle(0, 0, 16, 16);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            if (curtile.V >= 0) // Switch Track, Y is back tile if not -1
                                            {
                                                Vector2Int32 uvback = TrackUV(curtile.V);
                                                source.X = uvback.X * (source.Width + 2);
                                                source.Y = uvback.Y * (source.Height + 2);
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrackBack);
                                            }
                                            if ((curtile.U >= 2 && curtile.U <= 3) || (curtile.U >= 10 && curtile.U <= 13))
                                            { // Adding regular endcap
                                                dest.Y = 1 + (int)((_scrollPosition.Y + y - 1) * _zoom);
                                                source.X = 0;
                                                source.Y = 126;
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                            }
                                            if (curtile.U >= 24 && curtile.U <= 29)
                                            { // Adding bumper endcap
                                                dest.Y = 1 + (int)((_scrollPosition.Y + y - 1) * _zoom);
                                                source.X = 18;
                                                source.Y = 126;
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                            }
                                            if (curtile.U == 4 || curtile.U == 9 || curtile.U == 10 || curtile.U == 16 || curtile.U == 26 || curtile.U == 33 || curtile.U == 35 || curtile.V == 4)
                                            { // Adding angle track bottom right
                                                dest.Y = 1 + (int)((_scrollPosition.Y + y + 1) * _zoom);
                                                source.X = 0;
                                                source.Y = 108;
                                                for (int slice = 0; slice < 6; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, 12 - slice * 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y);

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTrack);
                                                }
                                            }
                                            if (curtile.U == 5 || curtile.U == 8 || curtile.U == 11 || curtile.U == 17 || curtile.U == 27 || curtile.U == 32 || curtile.U == 34 || curtile.V == 5)
                                            { // Adding angle track bottom left
                                                dest.Y =  1 + (int)((_scrollPosition.Y + y + 1) * _zoom);
                                                source.X = 18;
                                                source.Y = 108;
                                                for (int slice = 2; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 - 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y);

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTrack);
                                                }
                                            }
                                            dest.Y =  1 + (int)((_scrollPosition.Y + y) * _zoom);
                                            Vector2Int32 uv = TrackUV(curtile.U);
                                            source.X = uv.X * (source.Width + 2);
                                            source.Y = uv.Y * (source.Height + 2);

                                        }
                                        else if (isTreeSpecial)
                                        {
                                            source = new Rectangle(0, 0, 40, 40);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            FrameAnchor frameAnchor = FrameAnchor.None;

                                            int treeStyle = (curtile.uvTileCache & 0x000F);
                                            if (isBase)
                                            {
                                                source.Width = 80;
                                                source.Height = 80;
                                                if (curtile.Type == 323)
                                                {
                                                    source.Y = treeStyle * (source.Height + 2);
                                                    source.X = ((curtile.U - 88) / 22) * (source.Width + 2);
                                                    dest.X += (int)(curtile.V * _zoom / 16);
                                                }
                                                else
                                                {
                                                    switch (treeStyle)
                                                    {
                                                        case 2:
                                                        case 11:
                                                        case 13:
                                                            source.Width = 114;
                                                            source.Height = 96;
                                                            break;
                                                        case 3:
                                                            source.X = (x % 3) * (82 * 3);
                                                            source.Height = 140;
                                                            break;
                                                    }
                                                    source.X += ((curtile.V - 198) / 22) * (source.Width + 2);
                                                }
                                                frameAnchor = FrameAnchor.Bottom;
                                            }
                                            else if (isLeft)
                                            {
                                                source.X = 0;
                                                switch (treeStyle)
                                                {
                                                    case 3:
                                                        source.Y = (x % 3) * (42 * 3);
                                                        break;
                                                }
                                                frameAnchor = FrameAnchor.Right;
                                                source.Y += ((curtile.V - 198) / 22) * (source.Height + 2);
                                            }
                                            else if (isRight)
                                            {
                                                source.X = 42;
                                                switch (treeStyle)
                                                {
                                                    case 3:
                                                        source.Y = (x % 3) * (42 * 3);
                                                        break;
                                                }
                                                frameAnchor = FrameAnchor.Left;
                                                source.Y += ((curtile.V - 198) / 22) * (source.Height + 2);
                                            }
                                            dest.Width = (int)(_zoom * source.Width / 16f);
                                            dest.Height = (int)(_zoom * source.Height / 16f);
                                            switch (frameAnchor)
                                            {
                                                case FrameAnchor.None:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Left:
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Right:
                                                    dest.X += (int)((16 - source.Width) * _zoom / 16);
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Top:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Bottom:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    dest.Y += (int)((16 - source.Height) * _zoom / 16);
                                                    break;
                                            }
                                        }
                                        else if (isMushroom)
                                        {
                                            source = new Rectangle(0, 0, 60, 42);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                            source.X = (curtile.V / 18) * 62;

                                            dest.Width = (int)(_zoom * source.Width / 16f);
                                            dest.Height = (int)(_zoom * source.Height / 16f);
                                            dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                            dest.Y += (int)((16 - source.Height) * _zoom / 16);
                                        }
                                        else if ((curtile.Type >= 373 && curtile.Type <= 375) || curtile.Type == 461)
                                        {
                                          //skip rendering drips
                                        }
                                        else
                                        {
                                            source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            if (source.Width <= 0)
                                                source.Width = 16;
                                            if (source.Height <= 0)
                                                source.Height = 16;

                                            if (source.Bottom > tileTex.Height)
                                                source.Height -= (source.Bottom - tileTex.Height);
                                            if (source.Right > tileTex.Width)
                                                source.Width -= (source.Right - tileTex.Width);

                                            if (source.Width <= 0 || source.Height <= 0)
                                                continue;

                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            if (curtile.Type == 323)
                                            {
                                                dest.X += (int)(curtile.V * _zoom / 16);
                                                int treeType = (curtile.uvTileCache & 0x000F);
                                                source.Y = 22 * treeType;
                                            }
                                            var texsize = tileprop.TextureGrid;
                                            if (texsize.X != 16 || texsize.Y != 16)
                                            {
                                                dest.Width = (int)(texsize.X * (_zoom / 16));
                                                dest.Height = (int)(texsize.Y * (_zoom / 16));

                                                var frame = (tileprop.Frames.FirstOrDefault(f => f.UV == new Vector2Short(curtile.U, curtile.V)));
                                                var frameAnchor = FrameAnchor.None;
                                                if (frame != null)
                                                    frameAnchor = frame.Anchor;
                                                switch (frameAnchor)
                                                {
                                                    case FrameAnchor.None:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Left:
                                                        //position.X += (16 - texsize.X) / 2;
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Right:
                                                        dest.X += (int)((16 - texsize.X) * _zoom / 16);
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Top:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        //position.Y += (16 - texsize.Y);
                                                        break;
                                                    case FrameAnchor.Bottom:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        dest.Y += (int)((16 - texsize.Y) * _zoom / 16);
                                                        break;
                                                }
                                            }
                                        }

                                        _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                        // Actuator Overlay
                                        if (curtile.Actuator && _wvm.ShowActuators)
                                            _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator);

                                    }
                                }
                                else if (tileprop.IsPlatform)
                                {
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if (tileTex != null)
                                    {
                                        Vector2Int32 uv;
                                        if (curtile.uvTileCache == 0xFFFF)
                                        {
                                            uv = new Vector2Int32(0, 0);
                                            byte state = 0x00;
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x01 : 0x00);
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsSolid && neighborTile[w].Type != curtile.Type) ? 0x02 : 0x00);
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x04 : 0x00);
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsSolid && neighborTile[e].Type != curtile.Type) ? 0x08 : 0x00);
                                            switch (state)
                                            {
                                                case 0x00:
                                                case 0x0A:
                                                    uv.X = 5;
                                                    break;
                                                case 0x01:
                                                    uv.X = 1;
                                                    break;
                                                case 0x02:
                                                    uv.X = 6;
                                                    break;
                                                case 0x04:
                                                    uv.X = 2;
                                                    break;
                                                case 0x05:
                                                    uv.X = 0;
                                                    break;
                                                case 0x06:
                                                    uv.X = 3;
                                                    break;
                                                case 0x08:
                                                    uv.X = 7;
                                                    break;
                                                case 0x09:
                                                    uv.X = 4;
                                                    break;
                                            }
                                            uv.Y = blendRules.randomVariation.Next(3);
                                            curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X);
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                        // Actuator Overlay
                                        if (curtile.Actuator && _wvm.ShowActuators)
                                            _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator);

                                    }
                                }
                                else if (tileprop.IsCactus)
                                {

                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if ((curtile.uvTileCache & 0x00FF) >= 24)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Crimson_Cactus");
                                    }
                                    else if ((curtile.uvTileCache & 0x00FF) >= 16)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Evil_Cactus");
                                    }
                                    else if ((curtile.uvTileCache & 0x00FF) >= 8)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Good_Cactus");
                                    }

                                    if (tileTex != null)
                                    {
                                        Vector2Int32 uv;
                                        if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false)
                                        {
                                            bool isLeft = false, isRight = false, isBase = false;

                                            //Has this cactus been base-evaluated yet?
                                            int neighborX = (neighborTile[w].uvTileCache & 0x00FF) % 8; //Why % 8? If X >= 8, use hallow, If X >= 16, use corruption
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isRight = true;
                                            }
                                            neighborX = neighborTile[e].uvTileCache & 0x00FF;
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isLeft = true;
                                            }
                                            neighborX = curtile.uvTileCache & 0x00FF;
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isBase = true;
                                            }

                                            //Evaluate Base
                                            if (isLeft == false && isRight == false && isBase == false)
                                            {
                                                int length1 = 0;
                                                int length2 = 0;
                                                while (true)
                                                {
                                                    Tile checkTile = (y + length1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + length1] : null;
                                                    if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type)
                                                    {
                                                        break;
                                                    }
                                                    length1++;
                                                }
                                                if (x + 1 < _wvm.CurrentWorld.TilesWide)
                                                {
                                                    while (true)
                                                    {
                                                        Tile checkTile = (y + length2) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + length2] : null;
                                                        if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type)
                                                        {
                                                            break;
                                                        }
                                                        length2++;
                                                    }
                                                }
                                                int baseX = 0;
                                                int baseY = length1;
                                                isBase = true;
                                                if (length2 >= length1)
                                                {
                                                    baseX = 1;
                                                    baseY = length2;
                                                    isBase = false;
                                                    isLeft = true;
                                                }
                                                for (int cy = y; cy < y + baseY; cy++)
                                                {
                                                    if (_wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache == 0xFFFF)
                                                    {
                                                        if (cy == y)
                                                        {
                                                            _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x00 << 8 + 0x00;
                                                        }
                                                        else
                                                        {
                                                            _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x01 << 8 + 0x00;
                                                        }
                                                    }
                                                }
                                            }

                                            uv = new Vector2Int32(0, 0);
                                            byte state = 0x00;
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x01 : 0x00);
                                            state |= (byte)((neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == curtile.Type) ? 0x02 : 0x00);
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x04 : 0x00);
                                            state |= (byte)((neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == curtile.Type) ? 0x08 : 0x00);
                                            //state |= (byte)((neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == curtile.Type) ? 0x10 : 0x00);
                                            //state |= (byte)((neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == curtile.Type) ? 0x20 : 0x00);
                                            state |= (byte)((neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == curtile.Type) ? 0x40 : 0x00);
                                            state |= (byte)((neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == curtile.Type) ? 0x80 : 0x00);

                                            if (isLeft)
                                            {
                                                uv.X = 3;
                                                if ((state & 0x08) != 0x00) //s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 1;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.Y = 0;
                                                    }
                                                }
                                                else //!s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 2;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.X = 6;
                                                        uv.Y = 2;
                                                    }
                                                }
                                            }
                                            if (isRight)
                                            {
                                                uv.X = 2;
                                                if ((state & 0x08) != 0x00) //s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 1;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.Y = 0;
                                                    }
                                                }
                                                else //!s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 2;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.X = 6;
                                                        uv.Y = 1;
                                                    }
                                                }
                                            }
                                            if (isBase)
                                            {
                                                if ((state & 0x02) != 0x00) //n
                                                {
                                                    uv.Y = 2;
                                                    if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se)
                                                    {
                                                        uv.X = 4;
                                                    }
                                                    else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw)
                                                    {
                                                        uv.X = 1;
                                                    }
                                                    else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se
                                                    {
                                                        uv.X = 5;
                                                    }
                                                    else
                                                    {
                                                        uv.X = 0;
                                                        uv.Y = 1;
                                                    }
                                                }
                                                else //!n
                                                {
                                                    uv.Y = 0;
                                                    if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se)
                                                    {
                                                        uv.X = 4;
                                                    }
                                                    else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw)
                                                    {
                                                        uv.X = 1;
                                                    }
                                                    else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se
                                                    {
                                                        uv.X = 5;
                                                    }
                                                    else
                                                    {
                                                        uv.X = 0;
                                                        uv.Y = 0;
                                                    }
                                                }
                                            }

                                            //Check if cactus is good or evil
                                            for (int i = 0; i < 100; i++)
                                            {
                                                int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0;
                                                Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null;
                                                if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.CrimsandBlock) //Crimson
                                                {
                                                    uv.X += 24;
                                                    break;
                                                }
                                                if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.EbonsandBlock) //Corruption
                                                {
                                                    uv.X += 16;
                                                    break;
                                                }
                                                else if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.PearlsandBlock) //Hallow
                                                {
                                                    uv.X += 8;
                                                    break;
                                                }
                                            }
                                            curtile.hasLazyChecked = true;

                                            curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X);
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle(((curtile.uvTileCache & 0x00FF) % 8) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                    }
                                }
                                else if (tileprop.CanBlend)
                                {
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if (tileTex != null)
                                    {
                                        if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false)
                                        {
                                            int sameStyle = 0x00000000;
                                            int mergeMask = 0x00000000;
                                            int strictness = 0;
                                            if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value == -1) //Basically for cobweb
                                            {
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive) ? 0x1000 : 0x0000;
                                            }
                                            else if (tileprop.IsStone) //Stone & Gems
                                            {
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsStone) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].IsStone) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsStone) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].IsStone) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].IsStone) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].IsStone) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].IsStone) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].IsStone) ? 0x10000000 : 0x00000000;
                                            }
                                            else //Everything else
                                            {
                                                //Join to nearby tiles if their merge type is this tile's type
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].MergeWith.HasValue && World.TileProperties[neighborTile[e].Type].MergeWith.Value == curtile.Type) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].MergeWith.HasValue && World.TileProperties[neighborTile[n].Type].MergeWith.Value == curtile.Type) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].MergeWith.HasValue && World.TileProperties[neighborTile[w].Type].MergeWith.Value == curtile.Type) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].MergeWith.HasValue && World.TileProperties[neighborTile[s].Type].MergeWith.Value == curtile.Type) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].MergeWith.HasValue && World.TileProperties[neighborTile[ne].Type].MergeWith.Value == curtile.Type) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[nw].Type].MergeWith.Value == curtile.Type) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[sw].Type].MergeWith.Value == curtile.Type) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].MergeWith.HasValue && World.TileProperties[neighborTile[se].Type].MergeWith.Value == curtile.Type) ? 0x10000000 : 0x00000000;
                                                //Join if nearby tiles have the same type as this tile's type
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && curtile.Type == neighborTile[e].Type) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && curtile.Type == neighborTile[n].Type) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && curtile.Type == neighborTile[w].Type) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && curtile.Type == neighborTile[s].Type) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && curtile.Type == neighborTile[ne].Type) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && curtile.Type == neighborTile[nw].Type) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && curtile.Type == neighborTile[sw].Type) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && curtile.Type == neighborTile[se].Type) ? 0x10000000 : 0x00000000;
                                            }
                                            if (curtile.hasLazyChecked == false)
                                            {
                                                bool lazyCheckReady = true;
                                                lazyCheckReady &= (neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[e].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[n].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[w].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[s].lazyMergeId != 0xFF);
                                                if (lazyCheckReady)
                                                {
                                                    sameStyle &= 0x11111110 | ((neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? 0x00000001 : ((neighborTile[e].lazyMergeId & 0x04) >> 2));
                                                    sameStyle &= 0x11111101 | ((neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? 0x00000010 : ((neighborTile[n].lazyMergeId & 0x08) << 1));
                                                    sameStyle &= 0x11111011 | ((neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? 0x00000100 : ((neighborTile[w].lazyMergeId & 0x01) << 8));
                                                    sameStyle &= 0x11110111 | ((neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? 0x00001000 : ((neighborTile[s].lazyMergeId & 0x02) << 11));
                                                    curtile.hasLazyChecked = true;
                                                }
                                            }
                                            if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value > -1) //Merges with a specific type
                                            {
                                                mergeMask |= (neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == tileprop.MergeWith.Value) ? 0x0001 : 0x0000;
                                                mergeMask |= (neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == tileprop.MergeWith.Value) ? 0x0010 : 0x0000;
                                                mergeMask |= (neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == tileprop.MergeWith.Value) ? 0x0100 : 0x0000;
                                                mergeMask |= (neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == tileprop.MergeWith.Value) ? 0x1000 : 0x0000;
                                                mergeMask |= (neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == tileprop.MergeWith.Value) ? 0x00010000 : 0x00000000;
                                                mergeMask |= (neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == tileprop.MergeWith.Value) ? 0x00100000 : 0x00000000;
                                                mergeMask |= (neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == tileprop.MergeWith.Value) ? 0x01000000 : 0x00000000;
                                                mergeMask |= (neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == tileprop.MergeWith.Value) ? 0x10000000 : 0x00000000;
                                                strictness = 1;
                                            }
                                            if (tileprop.IsGrass)
                                            {
                                                strictness = 2;
                                            }

                                            Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, (uint)mergeMask, strictness);
                                            curtile.uvTileCache = (ushort)((uvBlend.Y << 8) + uvBlend.X);
                                            curtile.lazyMergeId = blendRules.lazyMergeValidation[uvBlend.Y, uvBlend.X];
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);


                                        // hack for some slopes
                                        switch (curtile.BrickStyle)
                                        {

                                            case BrickStyle.HalfBrick:
                                                source.Height /= 2;
                                                dest.Y += (int)(_zoom * 0.5);
                                                dest.Height = (int)(_zoom / 2.0f);
                                                _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                                break;
                                            case BrickStyle.SlopeTopRight:

                                                for (int slice = 0; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, 16 - slice * 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), (int)(dest.Y + slice * _zoom / 8.0f));

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures);
                                                }

                                                break;
                                            case BrickStyle.SlopeTopLeft:
                                                for (int slice = 0; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 + 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), (int)(dest.Y + (7 - slice) * _zoom / 8.0f));

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures);
                                                }

                                                break;
                                            case BrickStyle.SlopeBottomRight:
                                                for (int slice = 0; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y + slice * 2, 2, 16 - slice * 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y);

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures);
                                                }

                                                break;
                                            case BrickStyle.SlopeBottomLeft:
                                                for (int slice = 0; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 + 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y);

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures);
                                                }

                                                break;
                                            case BrickStyle.Full:
                                            default:
                                                _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                                break;
                                        }


                                        // Actuator Overlay
                                        if (curtile.Actuator && _wvm.ShowActuators)
                                            _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator);

                                    }
                                }
                            }
                        }
                        if (_wvm.ShowRedWires || _wvm.ShowBlueWires || _wvm.ShowGreenWires || _wvm.ShowYellowWires)
                        {
                            var tileTex = (Texture2D)_textureDictionary.GetMisc("WiresNew");
                            if (tileTex != null)
                            {
                                int voffset = 0;
                                if (curtile.Type == 424)
                                    voffset = (curtile.U / 18 + 1) * 72;
                                if (curtile.Type == 445)
                                    voffset = 72;
                                if (curtile.WireRed && _wvm.ShowRedWires)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].WireRed == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].WireRed == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].WireRed == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].WireRed == true) ? 0x08 : 0x00);
                                    source.X = state * 18;
                                    source.Y = voffset;

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerRedWires);
                                }
                                if (curtile.WireBlue && _wvm.ShowBlueWires)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].WireBlue == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].WireBlue == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].WireBlue == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].WireBlue == true) ? 0x08 : 0x00);
                                    source.X = state * 18;
                                    source.Y = 18 + voffset;

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerBlueWires);
                                }
                                if (curtile.WireGreen && _wvm.ShowGreenWires)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].WireGreen == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].WireGreen == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].WireGreen == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].WireGreen == true) ? 0x08 : 0x00);
                                    source.X = state * 18;
                                    source.Y = 36 + voffset;

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerGreenWires);
                                }
                                if (curtile.WireYellow && _wvm.ShowYellowWires)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].WireYellow == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].WireYellow == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].WireYellow == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].WireYellow == true) ? 0x08 : 0x00);
                                    source.X = state * 18;
                                    source.Y = 54 + voffset;

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerYellowWires);
                                }
                            }
                        }
                        if (_wvm.ShowLiquid)
                        {
                            if (curtile.LiquidAmount > 0)
                            {
                                Texture2D tileTex = null;
                                if (curtile.LiquidType == LiquidType.Lava)
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(1);
                                }
                                else if (curtile.LiquidType == LiquidType.Honey)
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(11); // Not sure if yellow Desert water, or Honey, but looks fine.
                                }
                                else
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(0);
                                }

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                    float alpha = 1f;

                                    if (curtile.LiquidType != LiquidType.Lava)
                                    {
                                        alpha = 0.5f;
                                    }
                                    else
                                    {
                                        alpha = 0.85f;
                                    }

                                    if (neighborTile[n] != null && neighborTile[n].LiquidAmount > 0)
                                    {
                                        source.Y = 8;
                                        source.Height = 8;
                                    }
                                    else
                                    {
                                        source.Height = 4 + ((int)Math.Round(curtile.LiquidAmount * 6f / 255f)) * 2;
                                        dest.Height = (int)(source.Height * _zoom / 16f);
                                        dest.Y = 1 + (int)((_scrollPosition.Y + y) * _zoom + ((16 - source.Height) * _zoom / 16f));
                                    }

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White * alpha, 0f, default(Vector2), SpriteEffects.None, LayerLiquid);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 51
0
 public UndoTile(Vector2Int32 location, Tile tile)
 {
     Location = location;
     Tile = tile;
 }
        /* Heathtech */
        //Pretty much overwrote this whole function.  The original part is still intact, but much more hidden
        private void DrawSprites()
        {
            Rectangle visibleBounds = GetViewingArea();
            TEditXna.Terraria.Objects.BlendRules blendRules = TEditXna.Terraria.Objects.BlendRules.Instance;
            if (visibleBounds.Height * visibleBounds.Width < 25000)
            {
                //Extended the viewing space to give tiles time to cache their UV's
                for (int y = visibleBounds.Top - 1; y < visibleBounds.Bottom + 2; y++)
                {
                    for (int x = visibleBounds.Left - 1; x < visibleBounds.Right + 2; x++)
                    {
                        if (x < 0 || y < 0 || x >= _wvm.CurrentWorld.TilesWide || y >= _wvm.CurrentWorld.TilesHigh)
                        {
                            continue;
                        }

                        var curtile = _wvm.CurrentWorld.Tiles[x, y];
                        var tileprop = World.TileProperties[curtile.Type];

                        //Neighbor tiles are often used when dynamically determining which UV position to render
                        int e = 0, n = 1, w = 2, s = 3, ne = 4, nw = 5, sw = 6, se = 7;
                        Tile[] neighborTile = new Tile[8];
                        neighborTile[e] = (x + 1) < _wvm.CurrentWorld.TilesWide ? _wvm.CurrentWorld.Tiles[x + 1, y] : null;
                        neighborTile[n] = (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x, y - 1] : null;
                        neighborTile[w] = (x - 1) > 0 ? _wvm.CurrentWorld.Tiles[x - 1, y] : null;
                        neighborTile[s] = (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + 1] : null;
                        neighborTile[ne] = (x + 1) < _wvm.CurrentWorld.TilesWide && (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x + 1, y - 1] : null;
                        neighborTile[nw] = (x - 1) > 0 && (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x - 1, y - 1] : null;
                        neighborTile[sw] = (x - 1) > 0 && (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x - 1, y + 1] : null;
                        neighborTile[se] = (x + 1) < _wvm.CurrentWorld.TilesWide && (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + 1] : null;

                        if (_wvm.ShowWalls)
                        {
                            if (curtile.Wall > 0)
                            {
                                var wallTex = _textureDictionary.GetWall(curtile.Wall);

                                if (wallTex != null)
                                {
                                    if (curtile.uvWallCache == 0xFFFF)
                                    {
                                        int sameStyle = 0x00000000;
                                        sameStyle |= (neighborTile[e] != null && neighborTile[e].Wall == curtile.Wall) ? 0x0001 : 0x0000;
                                        sameStyle |= (neighborTile[n] != null && neighborTile[n].Wall == curtile.Wall) ? 0x0010 : 0x0000;
                                        sameStyle |= (neighborTile[w] != null && neighborTile[w].Wall == curtile.Wall) ? 0x0100 : 0x0000;
                                        sameStyle |= (neighborTile[s] != null && neighborTile[s].Wall == curtile.Wall) ? 0x1000 : 0x0000;
                                        Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, 0x00000000, 0);
                                        curtile.uvWallCache = (ushort)((uvBlend.Y << 8) + uvBlend.X);
                                    }

                                    var texsize = new Vector2Int32(32, 32);
                                    var source = new Rectangle((curtile.uvWallCache & 0x00FF) * (texsize.X + 4), (curtile.uvWallCache >> 8) * (texsize.Y + 4), texsize.X, texsize.Y);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x - 0.5) * _zoom), 1 + (int)((_scrollPosition.Y + y - 0.5) * _zoom), (int)_zoom * 2, (int)_zoom * 2);

                                    _spriteBatch.Draw(wallTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 1);
                                }
                            }
                        }
                        if (_wvm.ShowTiles)
                        {
                            if (curtile.IsActive)
                            {
                                if (tileprop.IsFramed)
                                {
                                    Rectangle source = new Rectangle(), dest = new Rectangle();
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    bool isTree = false, isMushroom = false;
                                    bool isLeft = false, isBase = false, isRight = false;
                                    if (curtile.Type == 5 && curtile.U >= 22 && curtile.V >= 198)
                                    {
                                        isTree = true;
                                        switch (curtile.U)
                                        {
                                            case 22: isBase = true; break;
                                            case 44: isLeft = true; break;
                                            case 66: isRight = true; break;
                                        }
                                        //Abuse uvTileCache to remember what type of tree it is, since potentially scanning a hundred of blocks PER tree tile sounds slow
                                        int treeType = (curtile.uvTileCache & 0x000F);

                                        if (treeType > 4) //Tree type not yet set
                                        {
                                            //Check tree type
                                            treeType = 0; //Default to normal in case no grass grows beneath the tree
                                            int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0;
                                            for (int i = 0; i < 100; i++)
                                            {
                                                Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null;
                                                bool found = true;
                                                if (checkTile != null && checkTile.IsActive)
                                                {
                                                    switch (checkTile.Type)
                                                    {
                                                        case 2: treeType = 0; break; //Normal
                                                        case 23: treeType = 1; break; //Corruption
                                                        case 60: treeType = 2; break; //Jungle
                                                        case 109: treeType = 3; break; //Hallow
                                                        case 147: treeType = 4; break; //Snow
                                                        case 199: treeType = 5; break; //Crimson
                                                        default: found = false; break;
                                                    }
                                                    if (found == true)
                                                    {
                                                        curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeType);
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        if (isBase)
                                        {
                                            tileTex = (Texture2D)_textureDictionary.GetTreeTops(treeType);
                                        }
                                        else
                                        {
                                            tileTex = (Texture2D)_textureDictionary.GetTreeBranches(treeType);
                                        }
                                    }
                                    if (curtile.Type == 72 && curtile.U >= 36)
                                    {
                                        isMushroom = true;
                                        tileTex = (Texture2D)_textureDictionary.GetShroomTop(0);
                                    }

                                    if (tileTex != null)
                                    {
                                        if (!isTree && !isMushroom)
                                        {
                                            source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            if (source.Width <= 0)
                                                source.Width = 16;
                                            if (source.Height <= 0)
                                                source.Height = 16;

                                            if (source.Bottom > tileTex.Height)
                                                source.Height -= (source.Bottom - tileTex.Height);
                                            if (source.Right > tileTex.Width)
                                                source.Width -= (source.Right - tileTex.Width);

                                            if (source.Width <= 0 || source.Height <= 0)
                                                continue;

                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            var texsize = tileprop.TextureGrid;
                                            if (texsize.X != 16 || texsize.Y != 16)
                                            {
                                                dest.Width = (int)(texsize.X * (_zoom / 16));
                                                dest.Height = (int)(texsize.Y * (_zoom / 16));

                                                var frame = (tileprop.Frames.FirstOrDefault(f => f.UV == new Vector2Short(curtile.U, curtile.V)));
                                                var frameAnchor = FrameAnchor.None;
                                                if (frame != null)
                                                    frameAnchor = frame.Anchor;
                                                switch (frameAnchor)
                                                {
                                                    case FrameAnchor.None:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Left:
                                                        //position.X += (16 - texsize.X) / 2;
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Right:
                                                        dest.X += (int)((16 - texsize.X) * _zoom / 16);
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Top:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        //position.Y += (16 - texsize.Y);
                                                        break;
                                                    case FrameAnchor.Bottom:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        dest.Y += (int)((16 - texsize.Y) * _zoom / 16);
                                                        break;
                                                }
                                            }
                                        }
                                        else if (isTree)
                                        {
                                            source = new Rectangle(0, 0, 40, 40);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            FrameAnchor frameAnchor = FrameAnchor.None;

                                            int treeType = (curtile.uvTileCache & 0x000F);
                                            if (isBase)
                                            {
                                                switch (treeType)
                                                {
                                                    case 0:
                                                    case 1:
                                                    case 4:
                                                        source.Width = 80;
                                                        source.Height = 80;
                                                        break;
                                                    case 2:
                                                        source.Width = 114;
                                                        source.Height = 96;
                                                        break;
                                                    case 3:
                                                        source.X = (x % 3) * (82 * 3);
                                                        source.Width = 80;
                                                        source.Height = 140;
                                                        break;
                                                }
                                                source.X += ((curtile.V - 198) / 22) * (source.Width + 2);
                                                frameAnchor = FrameAnchor.Bottom;
                                            }
                                            else if (isLeft)
                                            {
                                                source.X = 0;
                                                switch (treeType)
                                                {
                                                    case 3:
                                                        source.Y = (x % 3) * (42 * 3);
                                                        break;
                                                }
                                                frameAnchor = FrameAnchor.Right;
                                                source.Y += ((curtile.V - 198) / 22) * (source.Height + 2);
                                            }
                                            else if (isRight)
                                            {
                                                source.X = 42;
                                                switch (treeType)
                                                {
                                                    case 3:
                                                        source.Y = (x % 3) * (42 * 3);
                                                        break;
                                                }
                                                frameAnchor = FrameAnchor.Left;
                                                source.Y += ((curtile.V - 198) / 22) * (source.Height + 2);
                                            }
                                            dest.Width = (int)(_zoom * source.Width / 16f);
                                            dest.Height = (int)(_zoom * source.Height / 16f);
                                            switch (frameAnchor)
                                            {
                                                case FrameAnchor.None:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Left:
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Right:
                                                    dest.X += (int)((16 - source.Width) * _zoom / 16);
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Top:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Bottom:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    dest.Y += (int)((16 - source.Height) * _zoom / 16);
                                                    break;
                                            }
                                        }
                                        else if (isMushroom)
                                        {
                                            source = new Rectangle(0, 0, 60, 42);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                            source.X = (curtile.V / 18) * 62;

                                            dest.Width = (int)(_zoom * source.Width / 16f);
                                            dest.Height = (int)(_zoom * source.Height / 16f);
                                            dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                            dest.Y += (int)((16 - source.Height) * _zoom / 16);
                                        }

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                    }
                                }
                                else if (tileprop.IsPlatform)
                                {
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if (tileTex != null)
                                    {
                                        Vector2Int32 uv;
                                        if (curtile.uvTileCache == 0xFFFF)
                                        {
                                            uv = new Vector2Int32(0, 0);
                                            byte state = 0x00;
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x01 : 0x00);
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsSolid && neighborTile[w].Type != curtile.Type) ? 0x02 : 0x00);
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x04 : 0x00);
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsSolid && neighborTile[e].Type != curtile.Type) ? 0x08 : 0x00);
                                            switch (state)
                                            {
                                                case 0x00:
                                                case 0x0A:
                                                    uv.X = 5;
                                                    break;
                                                case 0x01:
                                                    uv.X = 1;
                                                    break;
                                                case 0x02:
                                                    uv.X = 6;
                                                    break;
                                                case 0x04:
                                                    uv.X = 2;
                                                    break;
                                                case 0x05:
                                                    uv.X = 0;
                                                    break;
                                                case 0x06:
                                                    uv.X = 3;
                                                    break;
                                                case 0x08:
                                                    uv.X = 7;
                                                    break;
                                                case 0x09:
                                                    uv.X = 4;
                                                    break;
                                            }
                                            uv.Y = blendRules.randomVariation.Next(3);
                                            curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X);
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                    }
                                }
                                else if (tileprop.IsCactus)
                                {

                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if ((curtile.uvTileCache & 0x00FF) >= 16)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Evil_Cactus");
                                    }
                                    else if ((curtile.uvTileCache & 0x00FF) >= 8)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Good_Cactus");
                                    }

                                    if (tileTex != null)
                                    {
                                        Vector2Int32 uv;
                                        if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false)
                                        {
                                            bool isLeft = false, isRight = false, isBase = false;

                                            //Has this cactus been base-evaluated yet?
                                            int neighborX = (neighborTile[w].uvTileCache & 0x00FF) % 8; //Why % 8? If X >= 8, use hallow, If X >= 16, use corruption
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isRight = true;
                                            }
                                            neighborX = neighborTile[e].uvTileCache & 0x00FF;
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isLeft = true;
                                            }
                                            neighborX = curtile.uvTileCache & 0x00FF;
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isBase = true;
                                            }

                                            //Evaluate Base
                                            if (isLeft == false && isRight == false && isBase == false)
                                            {
                                                int length1 = 0;
                                                int length2 = 0;
                                                while (true)
                                                {
                                                    Tile checkTile = (y + length1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + length1] : null;
                                                    if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type)
                                                    {
                                                        break;
                                                    }
                                                    length1++;
                                                }
                                                if (x + 1 < _wvm.CurrentWorld.TilesWide)
                                                {
                                                    while (true)
                                                    {
                                                        Tile checkTile = (y + length2) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + length2] : null;
                                                        if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type)
                                                        {
                                                            break;
                                                        }
                                                        length2++;
                                                    }
                                                }
                                                int baseX = 0;
                                                int baseY = length1;
                                                isBase = true;
                                                if (length2 >= length1)
                                                {
                                                    baseX = 1;
                                                    baseY = length2;
                                                    isBase = false;
                                                    isLeft = true;
                                                }
                                                for (int cy = y; cy < y + baseY; cy++)
                                                {
                                                    if (_wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache == 0xFFFF)
                                                    {
                                                        if (cy == y)
                                                        {
                                                            _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x00 << 8 + 0x00;
                                                        }
                                                        else
                                                        {
                                                            _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x01 << 8 + 0x00;
                                                        }
                                                    }
                                                }
                                            }

                                            uv = new Vector2Int32(0, 0);
                                            byte state = 0x00;
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x01 : 0x00);
                                            state |= (byte)((neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == curtile.Type) ? 0x02 : 0x00);
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x04 : 0x00);
                                            state |= (byte)((neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == curtile.Type) ? 0x08 : 0x00);
                                            //state |= (byte)((neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == curtile.Type) ? 0x10 : 0x00);
                                            //state |= (byte)((neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == curtile.Type) ? 0x20 : 0x00);
                                            state |= (byte)((neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == curtile.Type) ? 0x40 : 0x00);
                                            state |= (byte)((neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == curtile.Type) ? 0x80 : 0x00);

                                            if (isLeft)
                                            {
                                                uv.X = 3;
                                                if ((state & 0x08) != 0x00) //s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 1;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.Y = 0;
                                                    }
                                                }
                                                else //!s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 2;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.X = 6;
                                                        uv.Y = 2;
                                                    }
                                                }
                                            }
                                            if (isRight)
                                            {
                                                uv.X = 2;
                                                if ((state & 0x08) != 0x00) //s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 1;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.Y = 0;
                                                    }
                                                }
                                                else //!s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 2;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.X = 6;
                                                        uv.Y = 1;
                                                    }
                                                }
                                            }
                                            if (isBase)
                                            {
                                                if ((state & 0x02) != 0x00) //n
                                                {
                                                    uv.Y = 2;
                                                    if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se)
                                                    {
                                                        uv.X = 4;
                                                    }
                                                    else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw)
                                                    {
                                                        uv.X = 1;
                                                    }
                                                    else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se
                                                    {
                                                        uv.X = 5;
                                                    }
                                                    else
                                                    {
                                                        uv.X = 0;
                                                        uv.Y = 1;
                                                    }
                                                }
                                                else //!n
                                                {
                                                    uv.Y = 0;
                                                    if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se)
                                                    {
                                                        uv.X = 4;
                                                    }
                                                    else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw)
                                                    {
                                                        uv.X = 1;
                                                    }
                                                    else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se
                                                    {
                                                        uv.X = 5;
                                                    }
                                                    else
                                                    {
                                                        uv.X = 0;
                                                        uv.Y = 0;
                                                    }
                                                }
                                            }

                                            //Check if cactus is good or evil
                                            for (int i = 0; i < 100; i++)
                                            {
                                                int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0;
                                                Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null;
                                                if (checkTile != null && checkTile.IsActive && checkTile.Type == 112) //Corruption
                                                {
                                                    uv.X += 16;
                                                    break;
                                                }
                                                else if (checkTile != null && checkTile.IsActive && checkTile.Type == 116) //Hallow
                                                {
                                                    uv.X += 8;
                                                    break;
                                                }
                                            }
                                            curtile.hasLazyChecked = true;

                                            curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X);
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle(((curtile.uvTileCache & 0x00FF) % 8) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                    }
                                }
                                else if (tileprop.CanBlend)
                                {
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if (tileTex != null)
                                    {
                                        if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false)
                                        {
                                            int sameStyle = 0x00000000;
                                            int mergeMask = 0x00000000;
                                            int strictness = 0;
                                            if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value == -1) //Basically for cobweb
                                            {
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive) ? 0x1000 : 0x0000;
                                            }
                                            else if (tileprop.IsStone) //Stone & Gems
                                            {
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsStone) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].IsStone) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsStone) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].IsStone) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].IsStone) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].IsStone) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].IsStone) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].IsStone) ? 0x10000000 : 0x00000000;
                                            }
                                            else //Everything else
                                            {
                                                //Join to nearby tiles if their merge type is this tile's type
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].MergeWith.HasValue && World.TileProperties[neighborTile[e].Type].MergeWith.Value == curtile.Type) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].MergeWith.HasValue && World.TileProperties[neighborTile[n].Type].MergeWith.Value == curtile.Type) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].MergeWith.HasValue && World.TileProperties[neighborTile[w].Type].MergeWith.Value == curtile.Type) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].MergeWith.HasValue && World.TileProperties[neighborTile[s].Type].MergeWith.Value == curtile.Type) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].MergeWith.HasValue && World.TileProperties[neighborTile[ne].Type].MergeWith.Value == curtile.Type) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[nw].Type].MergeWith.Value == curtile.Type) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[sw].Type].MergeWith.Value == curtile.Type) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].MergeWith.HasValue && World.TileProperties[neighborTile[se].Type].MergeWith.Value == curtile.Type) ? 0x10000000 : 0x00000000;
                                                //Join if nearby tiles have the same type as this tile's type
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && curtile.Type == neighborTile[e].Type) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && curtile.Type == neighborTile[n].Type) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && curtile.Type == neighborTile[w].Type) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && curtile.Type == neighborTile[s].Type) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && curtile.Type == neighborTile[ne].Type) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && curtile.Type == neighborTile[nw].Type) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && curtile.Type == neighborTile[sw].Type) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && curtile.Type == neighborTile[se].Type) ? 0x10000000 : 0x00000000;
                                            }
                                            if (curtile.hasLazyChecked == false)
                                            {
                                                bool lazyCheckReady = true;
                                                lazyCheckReady &= (neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[e].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[n].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[w].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[s].lazyMergeId != 0xFF);
                                                if (lazyCheckReady)
                                                {
                                                    sameStyle &= 0x11111110 | ((neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? 0x00000001 : ((neighborTile[e].lazyMergeId & 0x04) >> 2));
                                                    sameStyle &= 0x11111101 | ((neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? 0x00000010 : ((neighborTile[n].lazyMergeId & 0x08) << 1));
                                                    sameStyle &= 0x11111011 | ((neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? 0x00000100 : ((neighborTile[w].lazyMergeId & 0x01) << 8));
                                                    sameStyle &= 0x11110111 | ((neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? 0x00001000 : ((neighborTile[s].lazyMergeId & 0x02) << 11));
                                                    curtile.hasLazyChecked = true;
                                                }
                                            }
                                            if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value > -1) //Merges with a specific type
                                            {
                                                mergeMask |= (neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == tileprop.MergeWith.Value) ? 0x0001 : 0x0000;
                                                mergeMask |= (neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == tileprop.MergeWith.Value) ? 0x0010 : 0x0000;
                                                mergeMask |= (neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == tileprop.MergeWith.Value) ? 0x0100 : 0x0000;
                                                mergeMask |= (neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == tileprop.MergeWith.Value) ? 0x1000 : 0x0000;
                                                mergeMask |= (neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == tileprop.MergeWith.Value) ? 0x00010000 : 0x00000000;
                                                mergeMask |= (neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == tileprop.MergeWith.Value) ? 0x00100000 : 0x00000000;
                                                mergeMask |= (neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == tileprop.MergeWith.Value) ? 0x01000000 : 0x00000000;
                                                mergeMask |= (neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == tileprop.MergeWith.Value) ? 0x10000000 : 0x00000000;
                                                strictness = 1;
                                            }
                                            if (tileprop.IsGrass)
                                            {
                                                strictness = 2;
                                            }

                                            Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, (uint)mergeMask, strictness);
                                            curtile.uvTileCache = (ushort)((uvBlend.Y << 8) + uvBlend.X);
                                            curtile.lazyMergeId = blendRules.lazyMergeValidation[uvBlend.Y, uvBlend.X];
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                    }
                                }
                            }
                        }
                        if (_wvm.ShowWires)
                        {
                            if (curtile.HasWire)
                            {
                                var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires");

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire == true) ? 0x08 : 0x00);
                                    Vector2Int32 uv = new Vector2Int32(0, 0);
                                    switch (state)
                                    {
                                        case 0x00: uv.X = 0; uv.Y = 3; break;
                                        case 0x01: uv.X = 4; uv.Y = 2; break;
                                        case 0x02: uv.X = 2; uv.Y = 2; break;
                                        case 0x03: uv.X = 2; uv.Y = 1; break;
                                        case 0x04: uv.X = 3; uv.Y = 2; break;
                                        case 0x05: uv.X = 1; uv.Y = 0; break;
                                        case 0x06: uv.X = 3; uv.Y = 1; break;
                                        case 0x07: uv.X = 0; uv.Y = 1; break;
                                        case 0x08: uv.X = 1; uv.Y = 2; break;
                                        case 0x09: uv.X = 0; uv.Y = 2; break;
                                        case 0x0A: uv.X = 0; uv.Y = 0; break;
                                        case 0x0B: uv.X = 2; uv.Y = 0; break;
                                        case 0x0C: uv.X = 4; uv.Y = 1; break;
                                        case 0x0D: uv.X = 4; uv.Y = 0; break;
                                        case 0x0E: uv.X = 3; uv.Y = 0; break;
                                        case 0x0F: uv.X = 1; uv.Y = 1; break;
                                    }
                                    source.X = uv.X * (source.Width + 2);
                                    source.Y = uv.Y * (source.Height + 2);

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                }
                            }
                            if (curtile.HasWire2)
                            {
                                var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires2");

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire2 == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire2 == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire2 == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire2 == true) ? 0x08 : 0x00);
                                    Vector2Int32 uv = new Vector2Int32(0, 0);
                                    switch (state)
                                    {
                                        case 0x00: uv.X = 0; uv.Y = 3; break;
                                        case 0x01: uv.X = 4; uv.Y = 2; break;
                                        case 0x02: uv.X = 2; uv.Y = 2; break;
                                        case 0x03: uv.X = 2; uv.Y = 1; break;
                                        case 0x04: uv.X = 3; uv.Y = 2; break;
                                        case 0x05: uv.X = 1; uv.Y = 0; break;
                                        case 0x06: uv.X = 3; uv.Y = 1; break;
                                        case 0x07: uv.X = 0; uv.Y = 1; break;
                                        case 0x08: uv.X = 1; uv.Y = 2; break;
                                        case 0x09: uv.X = 0; uv.Y = 2; break;
                                        case 0x0A: uv.X = 0; uv.Y = 0; break;
                                        case 0x0B: uv.X = 2; uv.Y = 0; break;
                                        case 0x0C: uv.X = 4; uv.Y = 1; break;
                                        case 0x0D: uv.X = 4; uv.Y = 0; break;
                                        case 0x0E: uv.X = 3; uv.Y = 0; break;
                                        case 0x0F: uv.X = 1; uv.Y = 1; break;
                                    }
                                    source.X = uv.X * (source.Width + 2);
                                    source.Y = uv.Y * (source.Height + 2);

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                }
                            }
                            if (curtile.HasWire3)
                            {
                                var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires3");

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire3 == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire3 == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire3 == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire3 == true) ? 0x08 : 0x00);
                                    Vector2Int32 uv = new Vector2Int32(0, 0);
                                    switch (state)
                                    {
                                        case 0x00: uv.X = 0; uv.Y = 3; break;
                                        case 0x01: uv.X = 4; uv.Y = 2; break;
                                        case 0x02: uv.X = 2; uv.Y = 2; break;
                                        case 0x03: uv.X = 2; uv.Y = 1; break;
                                        case 0x04: uv.X = 3; uv.Y = 2; break;
                                        case 0x05: uv.X = 1; uv.Y = 0; break;
                                        case 0x06: uv.X = 3; uv.Y = 1; break;
                                        case 0x07: uv.X = 0; uv.Y = 1; break;
                                        case 0x08: uv.X = 1; uv.Y = 2; break;
                                        case 0x09: uv.X = 0; uv.Y = 2; break;
                                        case 0x0A: uv.X = 0; uv.Y = 0; break;
                                        case 0x0B: uv.X = 2; uv.Y = 0; break;
                                        case 0x0C: uv.X = 4; uv.Y = 1; break;
                                        case 0x0D: uv.X = 4; uv.Y = 0; break;
                                        case 0x0E: uv.X = 3; uv.Y = 0; break;
                                        case 0x0F: uv.X = 1; uv.Y = 1; break;
                                    }
                                    source.X = uv.X * (source.Width + 2);
                                    source.Y = uv.Y * (source.Height + 2);

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                }
                            }
                        }
                        if (_wvm.ShowLiquid)
                        {
                            if (curtile.Liquid > 0)
                            {
                                Texture2D tileTex = null;
                                if (curtile.IsLava)
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(1);
                                }
                                else if (curtile.IsHoney)
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(11); // Not sure if yellow Desert water, or Honey, but looks fine.
                                }
                                else
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(0);
                                }

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                    float alpha = 1f;

                                    if (curtile.IsLava == false)
                                    {
                                        alpha = 0.5f;
                                    }
                                    else
                                    {
                                        alpha = 0.85f;
                                    }

                                    if (neighborTile[n] != null && neighborTile[n].Liquid > 0)
                                    {
                                        source.Y = 8;
                                        source.Height = 8;
                                    }
                                    else
                                    {
                                        source.Height = 4 + ((int)Math.Round(curtile.Liquid * 6f / 255f)) * 2;
                                        dest.Height = (int)(source.Height * _zoom / 16f);
                                        dest.Y = 1 + (int)((_scrollPosition.Y + y) * _zoom + ((16 - source.Height) * _zoom / 16f));
                                    }

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White * alpha, 0f, default(Vector2), SpriteEffects.None, 0);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 53
0
 public void SaveTile(Vector2Int32 p)
 {
     SaveTile(p.X, p.Y);
 }
 private void AddNpc(NpcName npc)
 {
     if (CurrentWorld != null)
     {
         if (!CurrentWorld.NPCs.Any(n => n.Name == npc.Character))
         {
             var spawn = new Vector2Int32(CurrentWorld.SpawnX, CurrentWorld.SpawnY);
             CurrentWorld.NPCs.Add(new NPC{Home = spawn, IsHomeless = true, Name = npc.Character, Position= new Vector2(spawn.X * 16, spawn.Y * 16), SpriteId = npc.Id});
             Points.Add(npc.Character);
             MessageBox.Show(string.Format("{1} ({0}) added to spawn.", npc.Character, npc.Name), "NPC Added");
         }
         else
         {
             MessageBox.Show(string.Format("{1} ({0}) is already on the map.", npc.Character, npc.Name), "NPC Exists");
         }
     }
 }
Exemplo n.º 55
0
        public static IEnumerable<Vector2Int32> FillEllipseCentered(Vector2Int32 center, Vector2Int32 radius)
        {
            int xr = radius.X;
            int yr = radius.Y;
            int xc = center.X;
            int yc = center.Y;

            if (xr >= 1 && yr >= 1)
            {

                // Init vars
                int uy, ly, lx, rx;
                int x = xr;
                int y = 0;
                int xrSqTwo = (xr * xr) << 1;
                int yrSqTwo = (yr * yr) << 1;
                int xChg = yr * yr * (1 - (xr << 1));
                int yChg = xr * xr;
                int err = 0;
                int xStopping = yrSqTwo * xr;
                int yStopping = 0;

                // Draw first set of points counter clockwise where tangent line slope > -1.
                while (xStopping >= yStopping)
                {
                    // Draw 4 quadrant points at once
                    uy = yc + y; // Upper half
                    ly = yc - y; // Lower half
                    //if (uy < 0) uy = 0; // Clip
                    //if (uy >= h) uy = h - 1; // ...
                    //if (ly < 0) ly = 0;
                    //if (ly >= h) ly = h - 1;
                    //uh = uy*w; // Upper half
                    //lh = ly*w; // Lower half

                    rx = xc + x;
                    lx = xc - x;
                    //if (rx < 0) rx = 0; // Clip
                    //if (rx >= w) rx = w - 1; // ...
                    //if (lx < 0) lx = 0;
                    //if (lx >= w) lx = w - 1;

                    // Draw line
                    for (int i = lx; i <= rx; i++)
                    {
                        yield return new Vector2Int32(i, uy); // Quadrant II to I (Actually two octants)
                        yield return new Vector2Int32(i, ly); // Quadrant III to IV
                    }

                    y++;
                    yStopping += xrSqTwo;
                    err += yChg;
                    yChg += xrSqTwo;
                    if ((xChg + (err << 1)) > 0)
                    {
                        x--;
                        xStopping -= yrSqTwo;
                        err += xChg;
                        xChg += yrSqTwo;
                    }
                }

                // ReInit vars
                x = 0;
                y = yr;
                uy = yc + y; // Upper half
                ly = yc - y; // Lower half
                //if (uy < 0) uy = 0; // Clip
                //if (uy >= h) uy = h - 1; // ...
                //if (ly < 0) ly = 0;
                //if (ly >= h) ly = h - 1;
                //uh = uy*w; // Upper half
                //lh = ly*w; // Lower half
                xChg = yr * yr;
                yChg = xr * xr * (1 - (yr << 1));
                err = 0;
                xStopping = 0;
                yStopping = xrSqTwo * yr;

                // Draw second set of points clockwise where tangent line slope < -1.
                while (xStopping <= yStopping)
                {
                    // Draw 4 quadrant points at once
                    rx = xc + x;
                    lx = xc - x;
                    //if (rx < 0) rx = 0; // Clip
                    //if (rx >= w) rx = w - 1; // ...
                    //if (lx < 0) lx = 0;
                    //if (lx >= w) lx = w - 1;

                    // Draw line
                    for (int i = lx; i <= rx; i++)
                    {
                        yield return new Vector2Int32(i, uy); // Quadrant II to I (Actually two octants)
                        yield return new Vector2Int32(i, ly); // Quadrant III to IV
                    }

                    x++;
                    xStopping += yrSqTwo;
                    err += xChg;
                    xChg += yrSqTwo;
                    if ((yChg + (err << 1)) > 0)
                    {
                        y--;
                        uy = yc + y; // Upper half
                        ly = yc - y; // Lower half
                        //if (uy < 0) uy = 0; // Clip
                        //if (uy >= h) uy = h - 1; // ...
                        //if (ly < 0) ly = 0;
                        //if (ly >= h) ly = h - 1;
                        //uh = uy*w; // Upper half
                        //lh = ly*w; // Lower half
                        yStopping -= xrSqTwo;
                        err += yChg;
                        yChg += xrSqTwo;
                    }
                }
            }
        }
Exemplo n.º 56
0
 public static IEnumerable<Vector2Int32> FillQuad(Vector2Int32 v1, Vector2Int32 v2, Vector2Int32 v3, Vector2Int32 v4)
 {
     return FillPolygon(new[] { v1, v2, v3, v4 });
 }
Exemplo n.º 57
0
        private static void LinearFloodFill(ref Vector2Int32 start, ref Vector2Int32 minBound, ref Vector2Int32 maxBound, Func<Vector2Int32, bool> validation, ref FloodFillRangeQueue ranges, ref HashSet<Vector2Int32> points)
        {
            //FIND LEFT EDGE OF COLOR AREA
            int lFillLoc = start.X; //the location to check/fill on the left

            int x = start.X;
            int y = start.Y;
            points.Add(start);
            while (true)
            {
                points.Add(new Vector2Int32(lFillLoc, y));

                // Preform validation for next point
                lFillLoc--;
                var curPoint = new Vector2Int32(lFillLoc, y);
                if (lFillLoc <= minBound.X || !validation(curPoint) || points.Contains(curPoint))
                    break;			 	 //exit loop if we're at edge of bitmap or match area

            }
            lFillLoc++;

            //FIND RIGHT EDGE OF COLOR AREA
            int rFillLoc = x; //the location to check/fill on the left

            while (true)
            {
                points.Add(new Vector2Int32(rFillLoc, y));

                rFillLoc++;
                var curPoint = new Vector2Int32(rFillLoc, y);
                if (rFillLoc >= maxBound.X || !validation(curPoint) || points.Contains(curPoint))
                    break;			 	 //exit loop if we're at edge of bitmap or color area

            }
            rFillLoc--;

            var r = new FloodFillRange(lFillLoc, rFillLoc, y);
            ranges.Enqueue(ref r);
        }
Exemplo n.º 58
0
 public static IEnumerable<Vector2Int32> FillRectangleCentered(Vector2Int32 center, Vector2Int32 size)
 {
     var offset = new Vector2Int32(center.X - size.X/2, center.Y - size.Y/2);
     return FillRectangle(offset, size);
 }
Exemplo n.º 59
0
 public bool ValidTileLocation(Vector2Int32 v)
 {
     return ValidTileLocation(v.X, v.Y);
 }
Exemplo n.º 60
0
        public static void Flood(Vector2Int32 start, Vector2Int32 minBound, Vector2Int32 maxBound, Func<Vector2Int32, bool> validation)
        {
            var ranges = new FloodFillRangeQueue();
            var points = new HashSet<Vector2Int32>();

            LinearFloodFill(ref start, ref minBound, ref maxBound, validation, ref ranges, ref points);

            while (ranges.Count > 0)
            {
                //**Get Next Range Off the Queue
                FloodFillRange range = ranges.Dequeue();

                //**Check Above and Below Each Pixel in the Floodfill Range
                int upY = range.Y - 1;//so we can pass the y coord by ref
                int downY = range.Y + 1;
                var curPoint = new Vector2Int32();
                for (int i = range.StartX; i <= range.EndX; i++)
                {
                    //*Start Fill Upwards
                    //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance
                    curPoint = new Vector2Int32(i, upY);
                    if (range.Y > 0 && (!points.Contains(curPoint) && validation(curPoint)))
                        LinearFloodFill(ref curPoint, ref minBound, ref maxBound, validation, ref ranges, ref points);

                    //*Start Fill Downwards
                    //if we're not below the bottom of the bitmap and the pixel below this one is within the color tolerance
                    curPoint = new Vector2Int32(i, downY);
                    if (range.Y < (maxBound.Y - 1) && (!points.Contains(curPoint) && validation(curPoint)))
                        LinearFloodFill(ref curPoint, ref minBound, ref maxBound, validation, ref ranges, ref points);
                }
            }
        }