␉␉␉new Vector2(1, 1)␊ |
␉␉};␊ |
␊ |
␉␉// Used to calculate texture coordinates␊ |
␉␉private static readonly float[] CornerOffsetX = new float[]␊ |
␉␉{␊ |
␉␉␉0.0f,␊ |
␉␉␉1.0f,␊ |
␉␉␉0.0f,␊ |
␉␉␉1.0f␊ |
␉␉};␊ |
␉␉private static readonly float[] CornerOffsetY = new float[]␊ |
␉␉{␊ |
␉␉␉0.0f,␊ |
␉␉␉0.0f,␊ |
␉␉␉1.0f,␊ |
␉␉␉1.0f␊ |
␉␉};␊ |
␊ |
␉␉#endregion␊ |
␊ |
␉␉#region Private Variables␊ |
|
␊ |
␉␉␉vertexInfo = new VertexPositionColorTexture[MAX_VERTICES];␊ |
␉␉␉spriteData = new SpriteInfo[MAX_SPRITES];␊ |
␉␉␉for (int i = 0; i < MAX_SPRITES; i += 1)␊ |
␉␉␉{␊ |
␉␉␉␉spriteData[i].vertices = new VertexPositionColorTexture[4];␊ |
␉␉␉}␊ |
␉␉␉vertexBuffer = new DynamicVertexBuffer(␊ |
␉␉␉␉graphicsDevice,␊ |
␉␉␉␉typeof(VertexPositionColorTexture),␊ |
|
␉␉␉␉Vector2.Zero,␊ |
␉␉␉␉0.0f,␊ |
␉␉␉␉0.0f,␊ |
␉␉␉␉0␊ |
␉␉␉␉0,␊ |
␉␉␉␉false␊ |
␉␉␉);␊ |
␉␉}␊ |
␊ |
|
␉␉␉␉Vector2.Zero,␊ |
␉␉␉␉0.0f,␊ |
␉␉␉␉0.0f,␊ |
␉␉␉␉0␊ |
␉␉␉␉0,␊ |
␉␉␉␉false␊ |
␉␉␉);␊ |
␉␉}␊ |
␊ |
|
␉␉␉␉origin,␊ |
␉␉␉␉rotation,␊ |
␉␉␉␉layerDepth,␊ |
␉␉␉␉(byte) effects␊ |
␉␉␉␉(byte) effects,␊ |
␉␉␉␉false␊ |
␉␉␉);␊ |
␉␉}␊ |
␊ |
|
␉␉␉␉origin,␊ |
␉␉␉␉rotation,␊ |
␉␉␉␉layerDepth,␊ |
␉␉␉␉(byte) effects␊ |
␉␉␉␉(byte) effects,␊ |
␉␉␉␉false␊ |
␉␉␉);␊ |
␉␉}␊ |
␊ |
|
␉␉␉␉Vector2.Zero,␊ |
␉␉␉␉0.0f,␊ |
␉␉␉␉0.0f,␊ |
␉␉␉␉SpriteInfo.DestSizeInPixels␊ |
␉␉␉␉0,␊ |
␉␉␉␉true␊ |
␉␉␉);␊ |
␉␉}␊ |
␊ |
|
␉␉␉␉Vector2.Zero,␊ |
␉␉␉␉0.0f,␊ |
␉␉␉␉0.0f,␊ |
␉␉␉␉SpriteInfo.DestSizeInPixels␊ |
␉␉␉␉0,␊ |
␉␉␉␉true␊ |
␉␉␉);␊ |
␉␉}␊ |
␊ |
|
␉␉␉␉origin,␊ |
␉␉␉␉rotation,␊ |
␉␉␉␉layerDepth,␊ |
␉␉␉␉(byte) ((int) effects | SpriteInfo.DestSizeInPixels)␊ |
␉␉␉␉(byte) effects,␊ |
␉␉␉␉true␊ |
␉␉␉);␊ |
␉␉}␊ |
␊ |
|
␉␉␉␉␉offset,␊ |
␉␉␉␉␉rotation,␊ |
␉␉␉␉␉layerDepth,␊ |
␉␉␉␉␉(byte) effects␊ |
␉␉␉␉␉(byte) effects,␊ |
␉␉␉␉␉false␊ |
␉␉␉␉);␊ |
␊ |
␉␉␉␉/* Add the character width and right-side bearing to the line␊ |
|
␉␉␉␉␉offset,␊ |
␉␉␉␉␉rotation,␊ |
␉␉␉␉␉layerDepth,␊ |
␉␉␉␉␉(byte) effects␊ |
␉␉␉␉␉(byte) effects,␊ |
␉␉␉␉␉false␊ |
␉␉␉␉);␊ |
␊ |
␉␉␉␉/* Add the character width and right-side bearing to the line␊ |
|
␉␉␉Vector2 origin,␊ |
␉␉␉float rotation,␊ |
␉␉␉float depth,␊ |
␉␉␉byte effects␊ |
␉␉␉byte effects,␊ |
␉␉␉bool destSizeInPixels␊ |
␉␉) {␊ |
␉␉␉if (numSprites >= MAX_SPRITES)␊ |
␉␉␉{␊ |
|
␉␉␉␉FlushBatch();␊ |
␉␉␉}␊ |
␊ |
␉␉␉// Calculate source/destination␊ |
␉␉␉spriteData[numSprites].destination = destination;␊ |
␉␉␉// Source/Destination/Origin Calculations␊ |
␉␉␉float sourceX, sourceY, sourceW, sourceH;␊ |
␉␉␉float destW = destination.Z;␊ |
␉␉␉float destH = destination.W;␊ |
␉␉␉float originX, originY;␊ |
␉␉␉if (sourceRectangle.HasValue)␊ |
␉␉␉{␊ |
␉␉␉␉spriteData[numSprites].source = sourceRectangle.Value;␊ |
␉␉␉␉if ((effects & SpriteInfo.DestSizeInPixels) != SpriteInfo.DestSizeInPixels)␊ |
␉␉␉␉float inverseTexW = 1.0f / (float) texture.Width;␊ |
␉␉␉␉float inverseTexH = 1.0f / (float) texture.Height;␊ |
␉␉␉␉sourceX = sourceRectangle.Value.X * inverseTexW;␊ |
␉␉␉␉sourceY = sourceRectangle.Value.Y * inverseTexH;␊ |
␉␉␉␉sourceW = Math.Max(␊ |
␉␉␉␉␉sourceRectangle.Value.Width,␊ |
␉␉␉␉␉MathHelper.MachineEpsilonFloat␊ |
␉␉␉␉) * inverseTexW;␊ |
␉␉␉␉sourceH = Math.Max(␊ |
␉␉␉␉␉sourceRectangle.Value.Height,␊ |
␉␉␉␉␉MathHelper.MachineEpsilonFloat␊ |
␉␉␉␉) * inverseTexH;␊ |
␉␉␉␉originX = (origin.X / sourceW) * inverseTexW;␊ |
␉␉␉␉originY = (origin.Y / sourceH) * inverseTexH;␊ |
␊ |
␉␉␉␉if (!destSizeInPixels)␊ |
␉␉␉␉{␊ |
␉␉␉␉␉spriteData[numSprites].destination.Z *= sourceRectangle.Value.Width;␊ |
␉␉␉␉␉spriteData[numSprites].destination.W *= sourceRectangle.Value.Height;␊ |
␉␉␉␉␉destW *= sourceRectangle.Value.Width;␊ |
␉␉␉␉␉destH *= sourceRectangle.Value.Height;␊ |
␉␉␉␉}␊ |
␉␉␉␉effects |= SpriteInfo.SourceInTexels | SpriteInfo.DestSizeInPixels;␊ |
␉␉␉}␊ |
␉␉␉else␊ |
␉␉␉{␊ |
␉␉␉␉spriteData[numSprites].source.X = 0;␊ |
␉␉␉␉spriteData[numSprites].source.Y = 0;␊ |
␉␉␉␉spriteData[numSprites].source.Width = 1;␊ |
␉␉␉␉spriteData[numSprites].source.Height = 1;␊ |
␉␉␉␉sourceX = 0.0f;␊ |
␉␉␉␉sourceY = 0.0f;␊ |
␉␉␉␉sourceW = 1.0f;␊ |
␉␉␉␉sourceH = 1.0f;␊ |
␉␉␉␉originX = origin.X * (1.0f / (float) texture.Width);␊ |
␉␉␉␉originY = origin.Y * (1.0f / (float) texture.Height);␊ |
␉␉␉␉if (!destSizeInPixels)␊ |
␉␉␉␉{␊ |
␉␉␉␉␉destW *= texture.Width;␊ |
␉␉␉␉␉destH *= texture.Height;␊ |
␉␉␉␉}␊ |
␉␉␉}␊ |
␊ |
␉␉␉// Rotation Calculations␊ |
␉␉␉float rotationMatrix1X;␊ |
␉␉␉float rotationMatrix1Y;␊ |
␉␉␉float rotationMatrix2X;␊ |
␉␉␉float rotationMatrix2Y;␊ |
␉␉␉if (!MathHelper.WithinEpsilon(rotation, 0.0f))␊ |
␉␉␉{␊ |
␉␉␉␉float sin = (float) Math.Sin(rotation);␊ |
␉␉␉␉float cos = (float) Math.Cos(rotation);␊ |
␉␉␉␉rotationMatrix1X = cos;␊ |
␉␉␉␉rotationMatrix1Y = sin;␊ |
␉␉␉␉rotationMatrix2X = -sin;␊ |
␉␉␉␉rotationMatrix2Y = cos;␊ |
␉␉␉}␊ |
␉␉␉else␊ |
␉␉␉{␊ |
␉␉␉␉rotationMatrix1X = 1.0f;␊ |
␉␉␉␉rotationMatrix1Y = 0.0f;␊ |
␉␉␉␉rotationMatrix2X = 0.0f;␊ |
␉␉␉␉rotationMatrix2Y = 1.0f;␊ |
␉␉␉}␊ |
␊ |
␉␉␉// Everything else passed is just copied␊ |
␉␉␉spriteData[numSprites].texture = texture;␊ |
␉␉␉spriteData[numSprites].color = color;␊ |
␉␉␉spriteData[numSprites].origin = origin;␊ |
␉␉␉spriteData[numSprites].rotation = rotation;␊ |
␉␉␉spriteData[numSprites].depth = depth;␊ |
␉␉␉spriteData[numSprites].effects = effects;␊ |
␉␉␉// Calculate vertices, finally.␊ |
␉␉␉for (int j = 0, curVertex = numSprites * 4; j < 4; j += 1, curVertex += 1)␊ |
␉␉␉{␊ |
␉␉␉␉float cornerX = (CornerOffsetX[j] - originX) * destW;␊ |
␉␉␉␉float cornerY = (CornerOffsetY[j] - originY) * destH;␊ |
␉␉␉␉spriteData[numSprites].vertices[j].Position.X = (␊ |
␉␉␉␉␉(rotationMatrix2X * cornerY) +␊ |
␉␉␉␉␉(rotationMatrix1X * cornerX) +␊ |
␉␉␉␉␉destination.X␊ |
␉␉␉␉);␊ |
␉␉␉␉spriteData[numSprites].vertices[j].Position.Y = (␊ |
␉␉␉␉␉(rotationMatrix2Y * cornerY) +␊ |
␉␉␉␉␉(rotationMatrix1Y * cornerX) +␊ |
␉␉␉␉␉destination.Y␊ |
␉␉␉␉);␊ |
␉␉␉␉spriteData[numSprites].vertices[j].Position.Z = depth;␊ |
␉␉␉␉spriteData[numSprites].vertices[j].Color = color;␊ |
␉␉␉␉spriteData[numSprites].vertices[j].TextureCoordinate.X = (CornerOffsetX[j ^ effects] * sourceW) + sourceX;␊ |
␉␉␉␉spriteData[numSprites].vertices[j].TextureCoordinate.Y = (CornerOffsetY[j ^ effects] * sourceH) + sourceY;␊ |
␉␉␉}␊ |
␊ |
␉␉␉numSprites += 1;␊ |
␉␉␉if (sortMode == SpriteSortMode.Immediate)␊ |
␉␉␉{␊ |
␉␉␉␉PushVertices();␊ |
␉␉␉␉// FIXME: Make sorting less dump, then remove this -flibit␊ |
␉␉␉␉vertexInfo[0] = spriteData[0].vertices[0];␊ |
␉␉␉␉vertexInfo[1] = spriteData[0].vertices[1];␊ |
␉␉␉␉vertexInfo[2] = spriteData[0].vertices[2];␊ |
␉␉␉␉vertexInfo[3] = spriteData[0].vertices[3];␊ |
␉␉␉␉vertexBuffer.SetData(vertexInfo, 0, 4, SetDataOptions.None);␊ |
␉␉␉␉DrawPrimitives(texture, 0, 1);␊ |
␉␉␉␉numSprites = 0;␊ |
␉␉␉}␊ |
␉␉␉else␊ |
␉␉␉{␊ |
␉␉␉␉spriteData[numSprites].texture = texture;␊ |
␉␉␉␉spriteData[numSprites].depth = depth;␊ |
␉␉␉␉numSprites += 1;␊ |
␉␉␉}␊ |
␉␉}␊ |
␊ |
␉␉private void PushVertices()␊ |
␉␉{␊ |
␉␉␉for (int i = 0; i < numSprites; i += 1)␊ |
␉␉␉// FIXME: Make sorting less dump, then remove this -flibit␊ |
␉␉␉for (int i = 0, curVertex = 0; i < numSprites; i += 1, curVertex += 4)␊ |
␉␉␉{␊ |
␉␉␉␉/* FIXME: OPTIMIZATION POINT: This method␊ |
␉␉␉␉ * allocates like fuck right now! In general,␊ |
␉␉␉␉ * it's by far the slowest block of code in the␊ |
␉␉␉␉ * whole file, and needs fixing.␊ |
␉␉␉␉ * -flibit␊ |
␉␉␉␉ */␊ |
␊ |
␉␉␉␉// Current sprite being calculated␊ |
␉␉␉␉SpriteInfo info = spriteData[i];␊ |
␊ |
␉␉␉␉// Calculate initial sprite information␊ |
␉␉␉␉Vector2 source = new Vector2(␊ |
␉␉␉␉␉info.source.X,␊ |
␉␉␉␉␉info.source.Y␊ |
␉␉␉␉);␊ |
␉␉␉␉Vector2 destination = new Vector2(␊ |
␉␉␉␉␉info.destination.X,␊ |
␉␉␉␉␉info.destination.Y␊ |
␉␉␉␉);␊ |
␉␉␉␉Vector2 sourceSize = new Vector2(␊ |
␉␉␉␉␉Math.Max(␊ |
␉␉␉␉␉␉info.source.Width,␊ |
␉␉␉␉␉␉MathHelper.MachineEpsilonFloat␊ |
␉␉␉␉␉),␊ |
␉␉␉␉␉Math.Max(␊ |
␉␉␉␉␉␉info.source.Height,␊ |
␉␉␉␉␉␉MathHelper.MachineEpsilonFloat␊ |
␉␉␉␉␉)␊ |
␉␉␉␉);␊ |
␉␉␉␉Vector2 destinationSize = new Vector2(␊ |
␉␉␉␉␉info.destination.Z,␊ |
␉␉␉␉␉info.destination.W␊ |
␉␉␉␉);␊ |
␉␉␉␉Vector2 origin = info.origin / sourceSize;␊ |
␊ |
␉␉␉␉// Calculations performed with inverse texture size␊ |
␉␉␉␉Vector2 inverseTexSize = new Vector2(␊ |
␉␉␉␉␉(1.0f / (float) info.texture.Width),␊ |
␉␉␉␉␉(1.0f / (float) info.texture.Height)␊ |
␉␉␉␉);␊ |
␉␉␉␉if ((info.effects & SpriteInfo.SourceInTexels) == SpriteInfo.SourceInTexels)␊ |
␉␉␉␉{␊ |
␉␉␉␉␉source *= inverseTexSize;␊ |
␉␉␉␉␉sourceSize *= inverseTexSize;␊ |
␉␉␉␉}␊ |
␉␉␉␉else␊ |
␉␉␉␉{␊ |
␉␉␉␉␉origin *= inverseTexSize;␊ |
␉␉␉␉}␊ |
␊ |
␉␉␉␉// Calculations done with texture size␊ |
␉␉␉␉if ((info.effects & SpriteInfo.DestSizeInPixels) != SpriteInfo.DestSizeInPixels)␊ |
␉␉␉␉{␊ |
␉␉␉␉␉destinationSize.X *= info.texture.Width;␊ |
␉␉␉␉␉destinationSize.Y *= info.texture.Height;␊ |
␉␉␉␉}␊ |
␊ |
␉␉␉␉// Calculations performed with rotation␊ |
␉␉␉␉Vector2 rotationMatrix1;␊ |
␉␉␉␉Vector2 rotationMatrix2;␊ |
␉␉␉␉if (!MathHelper.WithinEpsilon(info.rotation, 0.0f))␊ |
␉␉␉␉{␊ |
␉␉␉␉␉float sin = (float) Math.Sin(info.rotation);␊ |
␉␉␉␉␉float cos = (float) Math.Cos(info.rotation);␊ |
␉␉␉␉␉rotationMatrix1.X = cos;␊ |
␉␉␉␉␉rotationMatrix1.Y = sin;␊ |
␉␉␉␉␉rotationMatrix2.X = -sin;␊ |
␉␉␉␉␉rotationMatrix2.Y = cos;␊ |
␉␉␉␉}␊ |
␉␉␉␉else␊ |
␉␉␉␉{␊ |
␉␉␉␉␉rotationMatrix1.X = 1.0f;␊ |
␉␉␉␉␉rotationMatrix1.Y = 0.0f;␊ |
␉␉␉␉␉rotationMatrix2.X = 0.0f;␊ |
␉␉␉␉␉rotationMatrix2.Y = 1.0f;␊ |
␉␉␉␉}␊ |
␊ |
␉␉␉␉// Calculate vertices, finally.␊ |
␉␉␉␉for (int j = 0, curVertex = i * 4; j < 4; j += 1, curVertex += 1)␊ |
␉␉␉␉{␊ |
␉␉␉␉␉Vector2 cornerOffset = (␊ |
␉␉␉␉␉␉SpriteInfo.CornerOffsets[j] - origin␊ |
␉␉␉␉␉) * destinationSize;␊ |
␊ |
␉␉␉␉␉Vector2 position = Vector2.Add(␊ |
␉␉␉␉␉␉Vector2.Multiply(␊ |
␉␉␉␉␉␉␉rotationMatrix2,␊ |
␉␉␉␉␉␉␉cornerOffset.Y␊ |
␉␉␉␉␉␉),␊ |
␉␉␉␉␉␉Vector2.Add(␊ |
␉␉␉␉␉␉␉Vector2.Multiply(␊ |
␉␉␉␉␉␉␉␉rotationMatrix1,␊ |
␉␉␉␉␉␉␉␉cornerOffset.X␊ |
␉␉␉␉␉␉␉),␊ |
␉␉␉␉␉␉␉destination␊ |
␉␉␉␉␉␉)␊ |
␉␉␉␉␉);␊ |
␉␉␉␉␉vertexInfo[curVertex].Position.X = position.X;␊ |
␉␉␉␉␉vertexInfo[curVertex].Position.Y = position.Y;␊ |
␉␉␉␉␉vertexInfo[curVertex].Position.Z = info.depth;␊ |
␉␉␉␉␉vertexInfo[curVertex].Color = info.color;␊ |
␉␉␉␉␉vertexInfo[curVertex].TextureCoordinate = Vector2.Add(␊ |
␉␉␉␉␉␉Vector2.Multiply(␊ |
␉␉␉␉␉␉␉SpriteInfo.CornerOffsets[j ^ (info.effects & 0x3)],␊ |
␉␉␉␉␉␉␉sourceSize␊ |
␉␉␉␉␉␉),␊ |
␉␉␉␉␉␉source␊ |
␉␉␉␉␉);␊ |
␉␉␉␉}␊ |
␉␉␉␉vertexInfo[curVertex] = spriteData[i].vertices[0];␊ |
␉␉␉␉vertexInfo[curVertex + 1] = spriteData[i].vertices[1];␊ |
␉␉␉␉vertexInfo[curVertex + 2] = spriteData[i].vertices[2];␊ |
␉␉␉␉vertexInfo[curVertex + 3] = spriteData[i].vertices[3];␊ |
␉␉␉}␊ |
␉␉␉vertexBuffer.SetData(vertexInfo, 0, numSprites * 4, SetDataOptions.None);␊ |
␉␉}␊ |
|
␊ |
␉␉private struct SpriteInfo␊ |
␉␉{␊ |
␉␉␉public Rectangle source;␊ |
␉␉␉public Vector4 destination;␊ |
␉␉␉public Color color;␊ |
␉␉␉public Vector2 origin;␊ |
␉␉␉public float rotation;␊ |
␉␉␉public float depth;␊ |
␉␉␉public VertexPositionColorTexture[] vertices;␊ |
␉␉␉public Texture2D texture;␊ |
␉␉␉public byte effects;␊ |
␊ |
␉␉␉public const int SourceInTexels = 0x4;␊ |
␉␉␉public const int DestSizeInPixels = 0x8;␊ |
␉␉␉public static readonly Vector2[] CornerOffsets = new Vector2[]␊ |
␉␉␉{␊ |
␉␉␉␉new Vector2(0.0f, 0.0f),␊ |
␉␉␉␉new Vector2(1.0f, 0.0f),␊ |
␉␉␉␉new Vector2(0.0f, 1.0f),␊ |
␉␉␉␉new Vector2(1.0f, 1.0f)␊ |
␉␉␉};␊ |
␉␉␉public float depth;␊ |
␉␉}␊ |
␊ |
␉␉#endregion␊ |