Exemple #1
0
    private Vector2 GetNeighbourPosition(Vector2 position, NeighbourIndex neighbour)
    {
        int evenY = Math.Abs((int)position.y) % 2;


        switch (neighbour)
        {
        case NeighbourIndex.NeighbourA:
            return(position + new Vector2(-1 + evenY, -1));

        case NeighbourIndex.NeighbourB:
            return(position + new Vector2(0 + evenY, -1));

        case NeighbourIndex.NeighbourC:
            return(position + new Vector2(1, 0));

        case NeighbourIndex.NeighbourD:
            return(position + new Vector2(0 + evenY, 1));

        case NeighbourIndex.NeighbourE:
            return(position + new Vector2(-1 + evenY, 1));

        case NeighbourIndex.NeighbourF:
            return(position + new Vector2(-1, 0));

        default:
            throw new ArgumentOutOfRangeException(nameof(neighbour), neighbour, null);
        }
    }
Exemple #2
0
        public List <IntPoint> GetHighlightFor(NeighbourIndex idx)
        {
            var points = new List <IntPoint>();

            switch (idx)
            {
            case NeighbourIndex.North:
                points.Add(Top);
                points.Add(Right);
                break;

            case NeighbourIndex.NorthEast:
                points.Add(MidPoint(Right, Top));
                points.Add(Right);
                points.Add(MidPoint(Right, Bottom));
                break;

            case NeighbourIndex.East:
                points.Add(Right);
                points.Add(Bottom);
                break;

            case NeighbourIndex.SouthEast:
                points.Add(MidPoint(Right, Bottom));
                points.Add(Bottom);
                points.Add(MidPoint(Left, Bottom));
                break;

            case NeighbourIndex.South:
                points.Add(Bottom);
                points.Add(Left);
                break;

            case NeighbourIndex.SouthWest:
                points.Add(MidPoint(Left, Bottom));
                points.Add(Left);
                points.Add(MidPoint(Left, Top));
                break;

            case NeighbourIndex.West:
                points.Add(Left);
                points.Add(Top);
                break;

            case NeighbourIndex.NorthWest:
                points.Add(MidPoint(Left, Top));
                points.Add(Top);
                points.Add(MidPoint(Right, Top));
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(idx), idx, null);
            }

            return(points);
        }
Exemple #3
0
        protected override void DrawIndexedDirection(SKCanvas g, TextureTile tile, NeighbourIndex idx)
        {
            var points = CreateShape(GetTileArea(tile)).ToHighlight().GetHighlightFor(idx);
            var brush  = Grid.TextureTileFormattingMetaData.TileHighlightColor ?? Preferences.DefaultTileHighlightColor;

            for (var pidx = 1; pidx < points.Count; pidx += 1)
            {
                var p1 = points[pidx - 1];
                var p2 = points[pidx];
                g.DrawRasterLine(brush, p1.X, p1.Y, p2.X, p2.Y);
            }
        }
Exemple #4
0
        public List <IntPoint> GetHighlightFor(NeighbourIndex idx)
        {
            var points = new List <IntPoint>();

            switch (idx)
            {
            case NeighbourIndex.North:
                points.Add(new IntPoint(Top.X - 1, Top.Y));
                points.Add(new IntPoint(Right.X - 1, Right.Y - 1));
                break;

            case NeighbourIndex.NorthEast:
                points.Add(MidPoint(new IntPoint(Right.X - 1, Right.Y - 1),
                                    new IntPoint(Top.X - 1, Top.Y)));
                points.Add(new IntPoint(Right.X - 1, Right.Y - 1));
                points.Add(new IntPoint(Right.X - 1, Right.Y));
                points.Add(MidPoint(new IntPoint(Right.X - 1, Right.Y),
                                    new IntPoint(Bottom.X - 1, Bottom.Y)));
                break;

            case NeighbourIndex.East:
                points.Add(new IntPoint(Right.X - 1, Right.Y));
                points.Add(new IntPoint(Bottom.X - 1, Bottom.Y));
                break;

            case NeighbourIndex.SouthEast:
                points.Add(MidPoint(new IntPoint(Right.X - 1, Right.Y),
                                    new IntPoint(Bottom.X - 1, Bottom.Y)));
                points.Add(new IntPoint(Bottom.X - 1, Bottom.Y));
                points.Add(new IntPoint(Bottom.X, Bottom.Y));
                points.Add(MidPoint(new IntPoint(Left.X + 1, Left.Y),
                                    new IntPoint(Bottom.X, Bottom.Y)));
                break;

            case NeighbourIndex.South:
                points.Add(new IntPoint(Bottom.X, Bottom.Y));
                points.Add(new IntPoint(Left.X + 1, Left.Y));
                break;

            case NeighbourIndex.SouthWest:
                points.Add(MidPoint(new IntPoint(Left.X + 1, Left.Y),
                                    new IntPoint(Bottom.X, Bottom.Y)));
                points.Add(new IntPoint(Left.X + 1, Left.Y));
                points.Add(new IntPoint(Left.X + 1, Left.Y - 1));
                points.Add(MidPoint(new IntPoint(Left.X + 1, Left.Y - 1),
                                    new IntPoint(Top.X, Top.Y)));
                break;

            case NeighbourIndex.West:
                points.Add(new IntPoint(Left.X + 1, Left.Y - 1));
                points.Add(new IntPoint(Top.X, Top.Y));
                break;

            case NeighbourIndex.NorthWest:
                points.Add(MidPoint(new IntPoint(Left.X + 1, Left.Y - 1),
                                    new IntPoint(Top.X, Top.Y)));
                points.Add(new IntPoint(Top.X, Top.Y));
                points.Add(new IntPoint(Top.X - 1, Top.Y));
                points.Add(MidPoint(new IntPoint(Right.X - 1, Right.Y - 1),
                                    new IntPoint(Top.X - 1, Top.Y)));
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(idx), idx, null);
            }

            return(points);
        }
Exemple #5
0
 public static int AsInt(this NeighbourIndex c)
 {
     return((int)c);
 }
Exemple #6
0
		public void GetNeighbourPointOverflow( long x, long y, out NeighbourIndex outindex, out long outx, out long outy )
		{
			outindex = NeighbourIndex.Count;
			if ( x < 0 )
			{
				outx = x + this.mSize - 1;
				if ( y < 0 )
				{
					outindex = NeighbourIndex.SouthWest;
				}
				else if ( y >= this.mSize )
				{
					outindex = NeighbourIndex.NorthWest;
				}
				else
				{
					outindex = NeighbourIndex.West;
				}
			}
			else if ( x >= this.mSize )
			{
				outx = x - this.mSize + 1;
				if ( y < 0 )
				{
					outindex = NeighbourIndex.SouthEast;
				}
				else if ( y >= this.mSize )
				{
					outindex = NeighbourIndex.NorthEast;
				}
				else
				{
					outindex = NeighbourIndex.East;
				}
			}
			else
			{
				outx = x;
			}

			if ( y < 0 )
			{
				outy = y + this.mSize - 1;
				if ( x >= 0 && x < this.mSize )
				{
					outindex = NeighbourIndex.South;
				}
			}
			else if ( y >= this.mSize )
			{
				outy = y - this.mSize + 1;
				if ( x >= 0 && x < this.mSize )
				{
					outindex = NeighbourIndex.North;
				}
			}
			else
			{
				outy = y;
			}

			System.Diagnostics.Debug.Assert( outindex != NeighbourIndex.Count );
		}
Exemple #7
0
		public void GetNeighbourPoint( NeighbourIndex index, long x, long y, ref long outx, ref long outy )
		{
			// Get the index of the point we should be looking at on a neighbour
			// in order to match up points
			System.Diagnostics.Debug.Assert( this.mSize == GetNeighbour( index ).Size,
											 "Neighbour has not the same size as this instance" );

			// left/right
			switch ( index )
			{
				case NeighbourIndex.East:
				case NeighbourIndex.NorthEast:
				case NeighbourIndex.SouthEast:
				case NeighbourIndex.West:
				case NeighbourIndex.NorthWest:
				case NeighbourIndex.SouthWest:
					outx = this.mSize - x - 1;
					break;

				default:
					outx = x;
					break;
			}
			;

			// top / bottom
			switch ( index )
			{
				case NeighbourIndex.North:
				case NeighbourIndex.NorthEast:
				case NeighbourIndex.NorthWest:
				case NeighbourIndex.South:
				case NeighbourIndex.SouthWest:
				case NeighbourIndex.SouthEast:
					outy = this.mSize - y - 1;
					break;

				default:
					outy = y;
					break;
			}
			;
		}
Exemple #8
0
		public void GetNeighbourEdgeRect( NeighbourIndex index, Rectangle inRect, ref Rectangle outRect )
		{
			System.Diagnostics.Debug.Assert( this.mSize == GetNeighbour( index ).Size,
											 "Neighbour has not the same size as this instance" );

			// Basically just reflect the rect 
			// remember index is neighbour relationship from OUR perspective so
			// arrangement is backwards to getEdgeRect

			// left/right
			switch ( index )
			{
				case NeighbourIndex.East:
				case NeighbourIndex.NorthEast:
				case NeighbourIndex.SouthEast:
				case NeighbourIndex.West:
				case NeighbourIndex.NorthWest:
				case NeighbourIndex.SouthWest:
					outRect.Left = this.mSize - inRect.Right;
					outRect.Right = this.mSize - inRect.Left;
					break;

				default:
					outRect.Left = inRect.Left;
					outRect.Right = inRect.Right;
					break;
			}
			;

			// top / bottom
			switch ( index )
			{
				case NeighbourIndex.North:
				case NeighbourIndex.NorthEast:
				case NeighbourIndex.NorthWest:
				case NeighbourIndex.South:
				case NeighbourIndex.SouthWest:
				case NeighbourIndex.SouthEast:
					outRect.Top = this.mSize - inRect.Bottom;
					outRect.Bottom = this.mSize - inRect.Top;
					break;

				default:
					outRect.Top = inRect.Top;
					outRect.Bottom = inRect.Bottom;
					break;
			}
			;
		}
Exemple #9
0
		public void GetEdgeRect( NeighbourIndex index, long range, ref Rectangle outRect )
		{
			// We make the edge rectangle 2 rows / columns at the edge of the tile
			// 2 because this copes with normal changes and potentially filtered
			// shadows.
			// all right / bottom values are exclusive
			// terrain origin is bottom-left remember so north is highest value

			// set left/right
			switch ( index )
			{
				case NeighbourIndex.East:
				case NeighbourIndex.NorthEast:
				case NeighbourIndex.SouthEast:
					outRect.Left = this.mSize - range;
					outRect.Right = this.mSize;
					break;

				case NeighbourIndex.West:
				case NeighbourIndex.NorthWest:
				case NeighbourIndex.SouthWest:
					outRect.Left = 0;
					outRect.Right = range;
					break;

				case NeighbourIndex.North:
				case NeighbourIndex.South:
					outRect.Left = 0;
					outRect.Right = this.mSize;
					break;

				case NeighbourIndex.Count:
				default:
					break;
			}
			;

			// set top / bottom
			switch ( index )
			{
				case NeighbourIndex.North:
				case NeighbourIndex.NorthEast:
				case NeighbourIndex.NorthWest:
					outRect.Top = this.mSize - range;
					outRect.Bottom = this.mSize;
					break;

				case NeighbourIndex.South:
				case NeighbourIndex.SouthWest:
				case NeighbourIndex.SouthEast:
					outRect.Top = 0;
					outRect.Bottom = range;
					break;

				case NeighbourIndex.East:
				case NeighbourIndex.West:
					outRect.Top = 0;
					outRect.Bottom = this.mSize;
					break;

				case NeighbourIndex.Count:
				default:
					break;
			}
			;
		}
Exemple #10
0
		public static NeighbourIndex GetOppositeNeighbour( NeighbourIndex index )
		{
			var intindex = (int)index;
			intindex += (int)( NeighbourIndex.Count )/2;
			intindex = intindex%(int)NeighbourIndex.Count;
			return (NeighbourIndex)intindex;
		}
Exemple #11
0
		/// <see cref="Terrain.SetNeighbour(NeighbourIndex, Terrain, bool, bool)"/>
		public void SetNeighbour( NeighbourIndex index, Terrain neighbour, bool recalculate )
		{
			SetNeighbour( index, neighbour, recalculate, true );
		}
Exemple #12
0
		/// <see cref="Terrain.SetNeighbour(NeighbourIndex, Terrain, bool, bool)"/>
		public void SetNeighbour( NeighbourIndex index, Terrain neighbour )
		{
			SetNeighbour( index, neighbour, false, true );
		}
Exemple #13
0
		public void SetNeighbour( NeighbourIndex index, Terrain neighbour, bool recalculate, bool notifyOther )
#endif
		{
			if ( this.mNeighbours[ (int)index ] != neighbour )
			{
				System.Diagnostics.Debug.Assert( neighbour != this, "Can't set self as own neighbour!" );

				// detach existing
				if ( this.mNeighbours[ (int)index ] != null && notifyOther )
				{
					this.mNeighbours[ (int)index ].SetNeighbour( GetOppositeNeighbour( index ), null, false, false );
				}

				this.mNeighbours[ (int)index ] = neighbour;
				if ( neighbour != null && notifyOther )
				{
					this.mNeighbours[ (int)index ].SetNeighbour( GetOppositeNeighbour( index ), this, recalculate, false );
				}

				if ( recalculate )
				{
					//recalculate, pass OUR edge rect
					var edgerect = new Rectangle();
					GetEdgeRect( index, 2, ref edgerect );
					NeighbourModified( index, edgerect, edgerect );
				}
			}
		}
Exemple #14
0
		public void SetNeighbour( NeighbourIndex index, Terrain neighbour, bool recalculate = false, bool notifyOther = true )
Exemple #15
0
		public Terrain GetNeighbour( NeighbourIndex index )
		{
			return this.mNeighbours[ (int)index ];
		}
Exemple #16
0
        protected override void DrawIndexedDirection(SKCanvas g, TextureTile tile, NeighbourIndex idx)
        {
            var points = new List <IntPoint>();

            var rect = GetTileHighlightArea(tile);

            var left    = rect.X;
            var top     = rect.Y;
            var right   = rect.X + rect.Width - 1;
            var bottom  = rect.Y + rect.Height - 1;
            var centerX = MidPoint(rect.X, rect.X + rect.Width);
            var centerY = MidPoint(rect.Y, rect.Y + rect.Height);

            switch (idx)
            {
            case NeighbourIndex.North:
                points.Add(new IntPoint(left, top));
                points.Add(new IntPoint(right, top));
                break;

            case NeighbourIndex.NorthEast:
                points.Add(new IntPoint(centerX, top));
                points.Add(new IntPoint(right, top));
                points.Add(new IntPoint(right, centerY));
                break;

            case NeighbourIndex.East:
                points.Add(new IntPoint(right, top));
                points.Add(new IntPoint(right, bottom));
                break;

            case NeighbourIndex.SouthEast:
                points.Add(new IntPoint(right, centerY));
                points.Add(new IntPoint(right, bottom));
                points.Add(new IntPoint(centerX, bottom));
                break;

            case NeighbourIndex.South:
                points.Add(new IntPoint(left, bottom));
                points.Add(new IntPoint(right, bottom));
                break;

            case NeighbourIndex.SouthWest:
                points.Add(new IntPoint(centerX, bottom));
                points.Add(new IntPoint(left, bottom));
                points.Add(new IntPoint(left, centerY));
                break;

            case NeighbourIndex.West:
                points.Add(new IntPoint(left, top));
                points.Add(new IntPoint(left, bottom));
                break;

            case NeighbourIndex.NorthWest:
                points.Add(new IntPoint(left, centerY));
                points.Add(new IntPoint(left, top));
                points.Add(new IntPoint(centerX, top));
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(idx), idx, null);
            }

            var pen = Grid.TextureTileFormattingMetaData.TileHighlightColor ?? Preferences.DefaultTileHighlightColor;

            g.DrawGeometry(pen, points);
        }
Exemple #17
0
		public void NeighbourModified( NeighbourIndex index, Rectangle edgerect, Rectangle shadowrect )
		{
			// We can safely assume that we would not have been contacted if it wasn't 
			// important
			var neighbour = GetNeighbour( index );
			if ( neighbour == null )
			{
				return; // bogus request
			}

			var updateGeom = false;
			byte updateDerived = 0;

			if ( !edgerect.IsNull )
			{
				// update edges; match heights first, then recalculate normals
				// reduce to just single line / corner
				var heightMatchRect = new Rectangle();
				GetEdgeRect( index, 1, ref heightMatchRect );
				heightMatchRect = heightMatchRect.Intersect( edgerect );

				for ( var y = heightMatchRect.Top; y < heightMatchRect.Bottom; ++y )
				{
					for ( var x = heightMatchRect.Left; x < heightMatchRect.Right; ++x )
					{
						long nx = 0, ny = 0;
						GetNeighbourPoint( index, x, y, ref nx, ref ny );
						var neighbourHeight = neighbour.GetHeightAtPoint( nx, ny );
						if ( !Utility.RealEqual( neighbourHeight, GetHeightAtPoint( x, y ), 1e-3f ) )
						{
							SetHeightAtPoint( x, y, neighbourHeight );
							if ( !updateGeom )
							{
								updateGeom = true;
								updateDerived |= DERIVED_DATA_ALL;
							}
						}
					}
				}
				// if we didn't need to update heights, we still need to update normals
				// because this was called only if neighbor changed
				if ( !updateGeom )
				{
					// ideally we would deal with normal dirty rect separately (as we do with
					// lightmaps) because a dirty geom rectangle will actually grow by one 
					// element in each direction for normals recalculation. However for
					// the sake of one row/column it's really not worth it.
					this.mDirtyDerivedDataRect.Merge( edgerect );
					updateDerived |= DERIVED_DATA_NORMALS;
				}
			}

			if ( !shadowrect.IsNull )
			{
				// update shadows
				// here we need to widen the rect passed in based on the min/max height 
				// of the *neighbour*
				var lightVec = TerrainGlobalOptions.LightMapDirection;
				var widenedRect = new Rectangle();
				WidenRectByVector( lightVec, shadowrect, neighbour.MinHeight, neighbour.MaxHeight, ref widenedRect );

				// set the special-case lightmap dirty rectangle
				this.mDirtyLightmapFromNeighboursRect.Merge( widenedRect );
				updateDerived |= DERIVED_DATA_LIGHTMAP;
			}

			if ( updateGeom )
			{
				UpdateGeometry();
			}
			if ( updateDerived != 0 )
			{
				UpdateDerivedData( false, updateDerived );
			}
		}