using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace MonoGame.Extended.Graphics { public static class GeometryBuilderExtensionsVertexPositionColorTexture { /// /// Adds a sprite to the back of specified . /// /// The . /// The vertex index offset applied to generated indices. /// The . /// The transform . /// /// The texture region of the . Use /// null to use the entire . /// /// /// The of the sprite. Use null to use the default size which is either /// the size of the if it is not null, or the texture size if /// is null. /// /// The . Use null to use the default . /// /// The origin . Use null to use the default /// . /// /// The . The default value is . /// The depth. The default value is 0. /// is null. /// /// The underlying /// is full. /// public static unsafe void EnqueueSprite(this GeometryBuffer geometryBuffer, ushort indexOffset, Texture2D texture, ref Matrix2D transformMatrix, Rectangle? sourceRectangle = null, Size? size = null, Color? color = null, Vector2? origin = null, SpriteEffects effects = SpriteEffects.None, float depth = 0) { if (texture == null) throw new ArgumentNullException(nameof(texture)); geometryBuffer.ThrowIfWouldOverflow(4, 6); var origin1 = origin ?? Vector2.Zero; Vector2 positionTopLeft, positionBottomRight, textureCoordinateTopLeft, textureCoordinateBottomRight; Size size1; if (sourceRectangle == null) { size1 = size ?? new Size(texture.Width, texture.Height); textureCoordinateTopLeft.X = 0; textureCoordinateTopLeft.Y = 0; textureCoordinateBottomRight.X = 1; textureCoordinateBottomRight.Y = 1; } else { var textureRegion = sourceRectangle.Value; size1 = size ?? new Size(textureRegion.Width, textureRegion.Height); textureCoordinateTopLeft.X = textureRegion.X/(float) texture.Width; textureCoordinateTopLeft.Y = textureRegion.Y/(float) texture.Height; textureCoordinateBottomRight.X = (textureRegion.X + textureRegion.Width)/(float) texture.Width; textureCoordinateBottomRight.Y = (textureRegion.Y + textureRegion.Height)/(float) texture.Height; } positionTopLeft.X = -origin1.X; positionTopLeft.Y = -origin1.Y; positionBottomRight.X = -origin1.X + size1.Width; positionBottomRight.Y = -origin1.Y + size1.Height; var spriteEffect = effects; if ((spriteEffect & SpriteEffects.FlipVertically) != 0) { var temp = textureCoordinateBottomRight.Y; textureCoordinateBottomRight.Y = textureCoordinateTopLeft.Y; textureCoordinateTopLeft.Y = temp; } if ((spriteEffect & SpriteEffects.FlipHorizontally) != 0) { var temp = textureCoordinateBottomRight.X; textureCoordinateBottomRight.X = textureCoordinateTopLeft.X; textureCoordinateTopLeft.X = temp; } var vertex = new VertexPositionColorTexture(new Vector3(Vector2.Zero, depth), color ?? Color.White, Vector2.Zero); fixed (VertexPositionColorTexture* fixedPointer = geometryBuffer._vertices) { var pointer = fixedPointer + geometryBuffer._vertexCount; // top-left var position = positionTopLeft; transformMatrix.Transform(position, out position); vertex.Position.X = position.X; vertex.Position.Y = position.Y; vertex.TextureCoordinate = textureCoordinateTopLeft; *(pointer + 0) = vertex; // top-right position.X = positionBottomRight.X; position.Y = positionTopLeft.Y; transformMatrix.Transform(position, out position); vertex.Position.X = position.X; vertex.Position.Y = position.Y; vertex.TextureCoordinate.X = textureCoordinateBottomRight.X; vertex.TextureCoordinate.Y = textureCoordinateTopLeft.Y; *(pointer + 1) = vertex; // bottom-left position.X = positionTopLeft.X; position.Y = positionBottomRight.Y; transformMatrix.Transform(position, out position); vertex.Position.X = position.X; vertex.Position.Y = position.Y; vertex.TextureCoordinate.X = textureCoordinateTopLeft.X; vertex.TextureCoordinate.Y = textureCoordinateBottomRight.Y; *(pointer + 2) = vertex; // bottom-right position = positionBottomRight; transformMatrix.Transform(position, out position); vertex.Position.X = position.X; vertex.Position.Y = position.Y; vertex.TextureCoordinate = textureCoordinateBottomRight; *(pointer + 3) = vertex; } geometryBuffer._vertexCount += 4; fixed (ushort* fixedPointer = geometryBuffer._indices) { var pointer = fixedPointer + geometryBuffer._indexCount; *(pointer + 0) = (ushort) (0 + indexOffset); *(pointer + 1) = (ushort) (1 + indexOffset); *(pointer + 2) = (ushort) (2 + indexOffset); *(pointer + 3) = (ushort) (1 + indexOffset); *(pointer + 4) = (ushort) (3 + indexOffset); *(pointer + 5) = (ushort) (2 + indexOffset); } geometryBuffer._indexCount += 6; } } }