private void RenderTiledSprite(SpriteRenderer spriteRenderer, SystemManagers managers)
{
float texelsWide = 0;
float texelsTall = 0;
int fullTexelsWide = 0;
int fullTexelsTall = 0;
if (this.AtlasedTexture != null)
{
fullTexelsWide = this.AtlasedTexture.SourceRectangle.Width;
fullTexelsTall = this.AtlasedTexture.SourceRectangle.Height;
}
else
{
fullTexelsWide = this.Texture.Width;
fullTexelsTall = this.Texture.Height;
}
texelsWide = fullTexelsWide;
if (SourceRectangle.HasValue)
{
texelsWide = SourceRectangle.Value.Width;
}
texelsTall = fullTexelsTall;
if (SourceRectangle.HasValue)
{
texelsTall = SourceRectangle.Value.Height;
}
float xRepetitions = texelsWide / (float)fullTexelsWide;
float yRepetitions = texelsTall / (float)fullTexelsTall;
if (xRepetitions > 0 && yRepetitions > 0)
{
float eachWidth = this.EffectiveWidth / xRepetitions;
float eachHeight = this.EffectiveHeight / yRepetitions;
float oldEffectiveWidth = this.EffectiveWidth;
float oldEffectiveHeight = this.EffectiveHeight;
// We're going to change the width, height, X, and Y of "this" to make rendering code work
// by simply passing in the object. At the end of the drawing, we'll revert the values back
// to what they were before rendering started.
float oldWidth = this.Width;
float oldHeight = this.Height;
float oldX = this.X;
float oldY = this.Y;
var oldSource = this.SourceRectangle.Value;
float texelsPerWorldUnitX = (float)fullTexelsWide / eachWidth;
float texelsPerWorldUnitY = (float)fullTexelsTall / eachHeight;
int oldSourceY = oldSource.Y;
if (oldSourceY < 0)
{
int amountToAdd = 1 - (oldSourceY / fullTexelsTall);
oldSourceY += amountToAdd * Texture.Height;
}
if (oldSourceY > 0)
{
int amountToAdd = System.Math.Abs(oldSourceY) / fullTexelsTall;
oldSourceY -= amountToAdd * Texture.Height;
}
float currentY = -oldSourceY * (1 / texelsPerWorldUnitY);
var matrix = this.GetRotationMatrix();
for (int y = 0; y < yRepetitions; y++)
{
float worldUnitsChoppedOffTop = System.Math.Max(0, oldSourceY * (1 / texelsPerWorldUnitY));
//float worldUnitsChoppedOffBottom = System.Math.Max(0, currentY + eachHeight - (int)oldEffectiveHeight);
float worldUnitsChoppedOffBottom = 0;
float extraY = yRepetitions - y;
if (extraY < 1)
{
worldUnitsChoppedOffBottom = System.Math.Max(0, (1 - extraY) * eachWidth);
}
int texelsChoppedOffTop = 0;
if (worldUnitsChoppedOffTop > 0)
{
texelsChoppedOffTop = oldSourceY;
}
int texelsChoppedOffBottom =
RenderingLibrary.Math.MathFunctions.RoundToInt(worldUnitsChoppedOffBottom * texelsPerWorldUnitY);
int sourceHeight = (int)(fullTexelsTall - texelsChoppedOffTop - texelsChoppedOffBottom);
if (sourceHeight == 0)
{
break;
}
this.Height = sourceHeight * 1 / texelsPerWorldUnitY;
int oldSourceX = oldSource.X;
if (oldSourceX < 0)
{
int amountToAdd = 1 - (oldSourceX / Texture.Width);
oldSourceX += amountToAdd * fullTexelsWide;
}
if (oldSourceX > 0)
{
int amountToAdd = System.Math.Abs(oldSourceX) / Texture.Width;
oldSourceX -= amountToAdd * fullTexelsWide;
}
float currentX = -oldSourceX * (1 / texelsPerWorldUnitX) + y * eachHeight * matrix.Up.X;
currentY = y * eachHeight * matrix.Up.Y;
for (int x = 0; x < xRepetitions; x++)
{
float worldUnitsChoppedOffLeft = System.Math.Max(0, oldSourceX * (1 / texelsPerWorldUnitX));
float worldUnitsChoppedOffRight = 0;
float extra = xRepetitions - x;
if (extra < 1)
{
worldUnitsChoppedOffRight = System.Math.Max(0, (1 - extra) * eachWidth);
}
int texelsChoppedOffLeft = 0;
if (worldUnitsChoppedOffLeft > 0)
{
// Let's use the hard number to not have any floating point issues:
//texelsChoppedOffLeft = worldUnitsChoppedOffLeft * texelsPerWorldUnit;
texelsChoppedOffLeft = oldSourceX;
}
int texelsChoppedOffRight =
RenderingLibrary.Math.MathFunctions.RoundToInt(worldUnitsChoppedOffRight * texelsPerWorldUnitX);
this.X = oldX + currentX + worldUnitsChoppedOffLeft;
this.Y = oldY + currentY + worldUnitsChoppedOffTop;
int sourceWidth = (int)(fullTexelsWide - texelsChoppedOffLeft - texelsChoppedOffRight);
if (sourceWidth == 0)
{
break;
}
this.Width = sourceWidth * 1 / texelsPerWorldUnitX;
if (AtlasedTexture != null)
{
var rectangle = new Rectangle(
AtlasedTexture.SourceRectangle.X + RenderingLibrary.Math.MathFunctions.RoundToInt(texelsChoppedOffLeft),
AtlasedTexture.SourceRectangle.Y + RenderingLibrary.Math.MathFunctions.RoundToInt(texelsChoppedOffTop),
sourceWidth,
sourceHeight);
Render(managers, spriteRenderer, this, AtlasedTexture.Texture, Color, rectangle, FlipHorizontal, FlipVertical, rotationInDegrees: Rotation);
}
else
{
this.SourceRectangle = new Rectangle(
RenderingLibrary.Math.MathFunctions.RoundToInt(texelsChoppedOffLeft),
RenderingLibrary.Math.MathFunctions.RoundToInt(texelsChoppedOffTop),
sourceWidth,
sourceHeight);
Render(managers, spriteRenderer, this, Texture, Color, SourceRectangle, FlipHorizontal, FlipVertical, rotationInDegrees: Rotation);
}
currentX = System.Math.Max(0, currentX);
currentX += this.Width * matrix.Right.X;
currentY += this.Width * matrix.Right.Y;
}
}
this.Width = oldWidth;
this.Height = oldHeight;
this.X = oldX;
this.Y = oldY;
this.SourceRectangle = oldSource;
}
}