/// <inheritdoc/> internal override void Draw <VertexType, SpriteData>(SpriteBatchBase <VertexType, SpriteData> spriteBatch, Vector2 position, Single width, Single height, Color color, Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth, SpriteData data) { effects |= SpriteEffects.OriginRelativeToDestination; position -= origin; var realOrigin = new Vector2( (int)((origin.X / width) * TextureRegion.Width), (int)((origin.Y / height) * TextureRegion.Height)); position += realOrigin; var srcRect = TextureRegion; var dstRect = new RectangleF(position.X, position.Y, width, height); spriteBatch.Draw(Texture, dstRect, srcRect, color, rotation, realOrigin, effects, layerDepth, data); }
/// <summary> /// Draws a tiled image segment. /// </summary> /// <typeparam name="VertexType">The type of vertex used to render the batch's sprites.</typeparam> /// <typeparam name="SpriteData">The type of data object associated with each of the batch's sprite instances.</typeparam> /// <param name="spriteBatch">The sprite batch with which to draw the segment.</param> /// <param name="tilingMode">A <see cref="TilingMode"/> value which specifies how to tile the image.</param> /// <param name="tilingData">A <see cref="TilingData"/> structure which contains the tiling parameters.</param> /// <param name="spriteData">The segment's custom sprite data.</param> protected static void TileImageSegment <VertexType, SpriteData>( SpriteBatchBase <VertexType, SpriteData> spriteBatch, TilingMode tilingMode, ref TilingData tilingData, SpriteData spriteData) where VertexType : struct, IVertexType where SpriteData : struct { var position = tilingData.Position; var origin = tilingData.Origin; var destinationRectangle = tilingData.DestinationRectangle; var sourceRectangle = tilingData.SourceRectangle; var tileHorizontally = (tilingMode & TilingMode.Horizontal) == TilingMode.Horizontal; var tileVertically = (tilingMode & TilingMode.Vertical) == TilingMode.Vertical; var tileCountX = tileHorizontally ? (Int32)Math.Ceiling(destinationRectangle.Width / sourceRectangle.Width) : 1; var tileCountY = tileVertically ? (Int32)Math.Ceiling(destinationRectangle.Height / sourceRectangle.Height) : 1; var cx = 0f; var cy = 0f; for (int y = 0; y < tileCountY; y++) { for (int x = 0; x < tileCountX; x++) { var srcTileWidth = Math.Min(sourceRectangle.Width, destinationRectangle.Width - cx); var srcTileHeight = Math.Min(sourceRectangle.Height, destinationRectangle.Height - cy); var dstTileWidth = tileHorizontally ? srcTileWidth : destinationRectangle.Width; var dstTileHeight = tileVertically ? srcTileHeight : destinationRectangle.Height; var tileRegion = new RectangleF(destinationRectangle.X, destinationRectangle.Y, dstTileWidth, dstTileHeight); var tileSource = new Rectangle(sourceRectangle.X, sourceRectangle.Y, (Int32)srcTileWidth, (Int32)srcTileHeight); var tilePosition = new Vector2(position.X + cx, position.Y + cy); var tileOrigin = origin - tilePosition; spriteBatch.Draw(tilingData.Texture, tileRegion, tileSource, tilingData.Color, tilingData.Rotation, tileOrigin, tilingData.Effects, tilingData.LayerDepth, spriteData); cx = cx + sourceRectangle.Width; } cx = 0; cy = cy + sourceRectangle.Height; } }
/// <summary> /// Draws a tiled image segment. /// </summary> /// <typeparam name="VertexType">The type of vertex used to render the batch's sprites.</typeparam> /// <typeparam name="SpriteData">The type of data object associated with each of the batch's sprite instances.</typeparam> /// <param name="mode">A <see cref="TilingMode"/> value which specifies how to tile the image.</param> /// <param name="spriteBatch">The sprite batch with which to draw the segment.</param> /// <param name="texture">The segment's texture.</param> /// <param name="position">The segment's position in screen coordinates.</param> /// <param name="destinationRectangle">A rectangle which indicates where on the screen the segment will be drawn.</param> /// <param name="sourceRectangle">The segment's position on its texture, or <see langword="null"/> to draw the entire texture.</param> /// <param name="color">The segment's tint color.</param> /// <param name="rotation">The segment's rotation in radians.</param> /// <param name="origin">The segment's origin point.</param> /// <param name="effects">The segment's rendering effects.</param> /// <param name="layerDepth">The segment's layer depth.</param> /// <param name="data">The segment's custom data.</param> protected static void TileImageSegment <VertexType, SpriteData>(TilingMode mode, SpriteBatchBase <VertexType, SpriteData> spriteBatch, Texture2D texture, Vector2 position, RectangleF destinationRectangle, Rectangle sourceRectangle, Color color, Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth, SpriteData data) where VertexType : struct, IVertexType where SpriteData : struct { var tileHorizontally = (mode & TilingMode.Horizontal) == TilingMode.Horizontal; var tileVertically = (mode & TilingMode.Vertical) == TilingMode.Vertical; var tileCountX = tileHorizontally ? (Int32)Math.Ceiling(destinationRectangle.Width / sourceRectangle.Width) : 1; var tileCountY = tileVertically ? (Int32)Math.Ceiling(destinationRectangle.Height / sourceRectangle.Height) : 1; var cx = 0f; var cy = 0f; for (int y = 0; y < tileCountY; y++) { for (int x = 0; x < tileCountX; x++) { var srcTileWidth = Math.Min(sourceRectangle.Width, destinationRectangle.Width - cx); var srcTileHeight = Math.Min(sourceRectangle.Height, destinationRectangle.Height - cy); var dstTileWidth = tileHorizontally ? srcTileWidth : destinationRectangle.Width; var dstTileHeight = tileVertically ? srcTileHeight : destinationRectangle.Height; var tileRegion = new RectangleF(destinationRectangle.X, destinationRectangle.Y, dstTileWidth, dstTileHeight); var tileSource = new Rectangle(sourceRectangle.X, sourceRectangle.Y, (Int32)srcTileWidth, (Int32)srcTileHeight); var tilePosition = new Vector2(position.X + cx, position.Y + cy); var tileOrigin = origin - tilePosition; spriteBatch.Draw(texture, tileRegion, tileSource, color, rotation, tileOrigin, effects, layerDepth, data); cx = cx + sourceRectangle.Width; } cx = 0; cy = cy + sourceRectangle.Height; } }
/// <summary> /// Draws horizontal images. /// </summary> private void DrawHorizontal <VertexType, SpriteData>(SpriteBatchBase <VertexType, SpriteData> spriteBatch, Vector2 position, Single width, Single height, Color color, Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth, SpriteData data) where VertexType : struct, IVertexType where SpriteData : struct { var srcLeft = this.Left; var srcRight = this.Right; var dstLeft = srcLeft; var dstRight = srcRight; if (width < MinimumRecommendedSize.Width) { var scale = width / MinimumRecommendedSize.Width; dstLeft = (Int32)Math.Floor(dstLeft * scale); dstRight = (Int32)Math.Ceiling(dstRight * scale); } var srcStretchableWidth = this.TextureRegion.Width - (srcLeft + srcRight); var srcStretchableHeight = this.TextureRegion.Height; var dstStretchableWidth = width - (dstLeft + dstRight); var dstStretchableHeight = height; // Center var centerSource = new Rectangle(this.TextureRegion.Left + srcLeft, this.TextureRegion.Top, srcStretchableWidth, srcStretchableHeight); var centerRegion = new RectangleF(position.X, position.Y, dstStretchableWidth, dstStretchableHeight); var centerPosition = new Vector2(dstLeft, 0); if (this.TileCenter) { TileImageSegment(TilingMode.Horizontal, spriteBatch, this.Texture, centerPosition, centerRegion, centerSource, color, rotation, origin, effects, layerDepth, data); } else { var centerOrigin = origin - centerPosition; spriteBatch.Draw(this.Texture, centerRegion, centerSource, color, rotation, centerOrigin, effects, layerDepth, data); } // Edges var leftSource = new Rectangle(this.TextureRegion.Left, this.TextureRegion.Top, srcLeft, srcStretchableHeight); var leftRegion = new RectangleF(position.X, position.Y, dstLeft, dstStretchableHeight); var leftPosition = new Vector2(0, 0); var rightSource = new Rectangle(this.TextureRegion.Right - srcRight, this.TextureRegion.Top, srcRight, srcStretchableHeight); var rightRegion = new RectangleF(position.X, position.Y, dstRight, dstStretchableHeight); var rightPosition = new Vector2(width - dstRight, 0); if (this.TileEdges) { TileImageSegment(TilingMode.Horizontal, spriteBatch, this.Texture, leftPosition, leftRegion, leftSource, color, rotation, origin, effects, layerDepth, data); TileImageSegment(TilingMode.Horizontal, spriteBatch, this.Texture, rightPosition, rightRegion, rightSource, color, rotation, origin, effects, layerDepth, data); } else { var leftOrigin = origin - leftPosition; spriteBatch.Draw(this.Texture, leftRegion, leftSource, color, rotation, leftOrigin, effects, layerDepth, data); var rightOrigin = origin - rightPosition; spriteBatch.Draw(this.Texture, rightRegion, rightSource, color, rotation, rightOrigin, effects, layerDepth, data); } }
/// <summary> /// Draws vertical images. /// </summary> private void DrawVertical <VertexType, SpriteData>(SpriteBatchBase <VertexType, SpriteData> spriteBatch, Vector2 position, Single width, Single height, Color color, Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth, SpriteData data) where VertexType : struct, IVertexType where SpriteData : struct { var srcTop = this.Left; var srcBottom = this.Right; var dstTop = srcTop; var dstBottom = srcBottom; if (height < MinimumRecommendedSize.Height) { var scale = height / MinimumRecommendedSize.Height; dstTop = (Int32)Math.Floor(dstTop * scale); dstBottom = (Int32)Math.Ceiling(dstBottom * scale); } var srcStretchableWidth = this.TextureRegion.Width; var srcStretchableHeight = this.TextureRegion.Height - (srcTop + srcBottom); var dstStretchableWidth = width; var dstStretchableHeight = height - (dstTop + dstBottom); // Center var centerSource = new Rectangle(this.TextureRegion.Left, this.TextureRegion.Top + srcTop, srcStretchableWidth, srcStretchableHeight); var centerRegion = new RectangleF(position.X, position.Y, dstStretchableWidth, dstStretchableHeight); var centerPosition = new Vector2(0, dstTop); if (this.TileCenter) { TileImageSegment(TilingMode.Vertical, spriteBatch, this.Texture, centerPosition, centerRegion, centerSource, color, rotation, origin, effects, layerDepth, data); } else { var centerOrigin = origin - centerPosition; spriteBatch.Draw(this.Texture, centerRegion, centerSource, color, rotation, centerOrigin, effects, layerDepth, data); } // Edges var topSource = new Rectangle(this.TextureRegion.Left, this.TextureRegion.Top, srcStretchableWidth, srcTop); var topRegion = new RectangleF(position.X, position.Y, dstStretchableWidth, dstTop); var topPosition = new Vector2(0, 0); var bottomSource = new Rectangle(this.TextureRegion.Left, this.TextureRegion.Bottom - srcBottom, srcStretchableWidth, srcBottom); var bottomRegion = new RectangleF(position.X, position.Y, dstStretchableWidth, dstBottom); var bottomPosition = new Vector2(0, height - dstBottom); if (this.TileEdges) { TileImageSegment(TilingMode.Vertical, spriteBatch, this.Texture, topPosition, topRegion, topSource, color, rotation, origin, effects, layerDepth, data); TileImageSegment(TilingMode.Vertical, spriteBatch, this.Texture, bottomPosition, bottomRegion, bottomSource, color, rotation, origin, effects, layerDepth, data); } else { var topOrigin = origin - topPosition; spriteBatch.Draw(this.Texture, topRegion, topSource, color, rotation, topOrigin, effects, layerDepth, data); var bottomOrigin = origin - bottomPosition; spriteBatch.Draw(this.Texture, bottomRegion, bottomSource, color, rotation, bottomOrigin, effects, layerDepth, data); } }
/// <inheritdoc/> internal override void Draw <VertexType, SpriteData>(SpriteBatchBase <VertexType, SpriteData> spriteBatch, Vector2 position, Single width, Single height, Color color, Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth, SpriteData data) { var tilingData = new TilingData() { Texture = this.Texture, Color = color, Rotation = rotation, Origin = origin, Effects = effects, LayerDepth = layerDepth }; effects |= SpriteEffects.OriginRelativeToDestination; var srcLeft = this.Left; var srcTop = this.Top; var srcRight = this.Right; var srcBottom = this.Bottom; var dstLeft = srcLeft; var dstTop = srcTop; var dstRight = srcRight; var dstBottom = srcBottom; if (width < MinimumRecommendedSize.Width) { var scale = width / MinimumRecommendedSize.Width; dstLeft = (Int32)Math.Floor(dstLeft * scale); dstRight = (Int32)Math.Ceiling(dstRight * scale); } if (height < MinimumRecommendedSize.Height) { var scale = height / MinimumRecommendedSize.Height; dstTop = (Int32)Math.Floor(dstTop * scale); dstBottom = (Int32)Math.Ceiling(dstBottom * scale); } var srcStretchableWidth = this.TextureRegion.Width - (srcLeft + srcRight); var srcStretchableHeight = this.TextureRegion.Height - (srcTop + srcBottom); var dstStretchableWidth = width - (dstLeft + dstRight); var dstStretchableHeight = height - (dstTop + dstBottom); // Center var centerSource = new Rectangle(this.TextureRegion.Left + srcLeft, this.TextureRegion.Top + srcTop, srcStretchableWidth, srcStretchableHeight); var centerRegion = new RectangleF(position.X, position.Y, dstStretchableWidth, dstStretchableHeight); var centerPosition = new Vector2(dstLeft, dstTop); if (this.TileCenter) { tilingData.Position = centerPosition; tilingData.DestinationRectangle = centerRegion; tilingData.SourceRectangle = centerSource; TileImageSegment(spriteBatch, TilingMode.Both, ref tilingData, data); } else { var centerOrigin = origin - centerPosition; spriteBatch.Draw(this.Texture, centerRegion, centerSource, color, rotation, centerOrigin, effects, layerDepth, data); } // Edges var leftSource = new Rectangle(this.TextureRegion.Left, this.TextureRegion.Top + srcTop, srcLeft, srcStretchableHeight); var leftRegion = new RectangleF(position.X, position.Y, dstLeft, dstStretchableHeight); var leftPosition = new Vector2(0, dstTop); var rightSource = new Rectangle(this.TextureRegion.Right - srcRight, this.TextureRegion.Top + srcTop, srcRight, srcStretchableHeight); var rightRegion = new RectangleF(position.X, position.Y, dstRight, dstStretchableHeight); var rightPosition = new Vector2(width - dstRight, dstTop); var topSource = new Rectangle(this.TextureRegion.Left + srcLeft, this.TextureRegion.Top, srcStretchableWidth, srcTop); var topRegion = new RectangleF(position.X, position.Y, dstStretchableWidth, dstTop); var topPosition = new Vector2(dstLeft, 0); var bottomSource = new Rectangle(this.TextureRegion.Left + srcLeft, this.TextureRegion.Bottom - srcBottom, srcStretchableWidth, srcBottom); var bottomRegion = new RectangleF(position.X, position.Y, dstStretchableWidth, dstBottom); var bottomPosition = new Vector2(dstLeft, height - dstBottom); if (this.TileEdges) { tilingData.Position = leftPosition; tilingData.DestinationRectangle = leftRegion; tilingData.SourceRectangle = leftSource; TileImageSegment(spriteBatch, TilingMode.Both, ref tilingData, data); tilingData.Position = rightPosition; tilingData.DestinationRectangle = rightRegion; tilingData.SourceRectangle = rightSource; TileImageSegment(spriteBatch, TilingMode.Both, ref tilingData, data); tilingData.Position = topPosition; tilingData.DestinationRectangle = topRegion; tilingData.SourceRectangle = topSource; TileImageSegment(spriteBatch, TilingMode.Both, ref tilingData, data); tilingData.Position = bottomPosition; tilingData.DestinationRectangle = bottomRegion; tilingData.SourceRectangle = bottomSource; TileImageSegment(spriteBatch, TilingMode.Both, ref tilingData, data); } else { var leftOrigin = origin - leftPosition; spriteBatch.Draw(this.Texture, leftRegion, leftSource, color, rotation, leftOrigin, effects, layerDepth, data); var rightOrigin = origin - rightPosition; spriteBatch.Draw(this.Texture, rightRegion, rightSource, color, rotation, rightOrigin, effects, layerDepth, data); var topOrigin = origin - topPosition; spriteBatch.Draw(this.Texture, topRegion, topSource, color, rotation, topOrigin, effects, layerDepth, data); var bottomOrigin = origin - bottomPosition; spriteBatch.Draw(this.Texture, bottomRegion, bottomSource, color, rotation, bottomOrigin, effects, layerDepth, data); } // Corners var cornerTLRegion = new RectangleF(position.X, position.Y, dstLeft, dstTop); var cornerTLPosition = new Vector2(0, 0); var cornerTLOrigin = origin - cornerTLPosition; var cornerTLSource = new Rectangle(this.TextureRegion.Left, this.TextureRegion.Top, srcLeft, srcTop); spriteBatch.Draw(this.Texture, cornerTLRegion, cornerTLSource, color, rotation, cornerTLOrigin, effects, layerDepth, data); var cornerTRRegion = new RectangleF(position.X, position.Y, dstRight, dstTop); var cornerTRPosition = new Vector2(width - dstRight, 0); var cornerTROrigin = origin - cornerTRPosition; var cornerTRSource = new Rectangle(this.TextureRegion.Right - srcRight, this.TextureRegion.Top, srcRight, srcTop); spriteBatch.Draw(this.Texture, cornerTRRegion, cornerTRSource, color, rotation, cornerTROrigin, effects, layerDepth, data); var cornerBLRegion = new RectangleF(position.X, position.Y, dstLeft, dstBottom); var cornerBLPosition = new Vector2(0, height - dstBottom); var cornerBLOrigin = origin - cornerBLPosition; var cornerBLSource = new Rectangle(this.TextureRegion.Left, this.TextureRegion.Bottom - srcBottom, srcLeft, srcBottom); spriteBatch.Draw(this.Texture, cornerBLRegion, cornerBLSource, color, rotation, cornerBLOrigin, effects, layerDepth, data); var cornerBRRegion = new RectangleF(position.X, position.Y, dstRight, dstBottom); var cornerBRPosition = new Vector2(width - dstRight, height - dstBottom); var cornerBROrigin = origin - cornerBRPosition; var cornerBRSource = new Rectangle(this.TextureRegion.Right - srcRight, this.TextureRegion.Bottom - srcBottom, srcLeft, srcBottom); spriteBatch.Draw(this.Texture, cornerBRRegion, cornerBRSource, color, rotation, cornerBROrigin, effects, layerDepth, data); }