using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MLEM.Misc; namespace MLEM.Textures { /// /// This class represents an atlas of objects that is uniform. /// Uniform, in this case, means that the texture atlas' size is not determined by the width and height of the texture, but instead by the amount of sub-regions that the atlas has in the x and y direction. /// Using a uniform texture atlas over a regular texture as an atlas allows for texture artists to create higher resolution textures without coordinates becoming off. /// public class UniformTextureAtlas : GenericDataHolder { /// /// The that this uniform texture atlas uses as its basis. /// In most cases, has the full area of the underlying . /// public readonly TextureRegion Region; /// /// The amount of sub-regions this atlas has in the x direction /// public readonly int RegionAmountX; /// /// The amount of sub-regions this atlas has in the y direction /// public readonly int RegionAmountY; /// /// The width of each region, based on the texture's width and the amount of regions /// public readonly int RegionWidth; /// /// The height of reach region, based on the texture's height and the amount of regions /// public readonly int RegionHeight; /// /// The texture to use for this atlas. /// Note that stores the actual area that we depend on. /// public Texture2D Texture => this.Region.Texture; /// /// Returns the at this texture atlas's given index. /// The index is zero-based, where rows come first and columns come second. /// /// The zero-based texture index public TextureRegion this[int index] => this[index % this.RegionAmountX, index / this.RegionAmountX]; /// /// Returns the at this texture atlas' given region position /// /// The region's x and y location public TextureRegion this[Point point] => this[new Rectangle(point.X, point.Y, 1, 1)]; /// public TextureRegion this[int x, int y] => this[new Point(x, y)]; /// /// Returns the at this texture atlas' given region position and size. /// Note that the region size is not in pixels, but in region units. /// /// The region's area public TextureRegion this[Rectangle rect] => this.GetOrAddRegion(rect); /// public TextureRegion this[int x, int y, int width, int height] => this[new Rectangle(x, y, width, height)]; private readonly Dictionary regions = new Dictionary(); /// /// Creates a new uniform texture atlas with the given texture region and region amount. /// This atlas will only ever pull information from the given and never exit the region's bounds. /// /// The texture region to use for this atlas /// The amount of texture regions in the x direction /// The amount of texture regions in the y direction public UniformTextureAtlas(TextureRegion region, int regionAmountX, int regionAmountY) { this.Region = region; this.RegionAmountX = regionAmountX; this.RegionAmountY = regionAmountY; this.RegionWidth = region.Width / regionAmountX; this.RegionHeight = region.Height / regionAmountY; } /// /// Creates a new uniform texture atlas with the given texture and region amount. /// /// The texture to use for this atlas /// The amount of texture regions in the x direction /// The amount of texture regions in the y direction public UniformTextureAtlas(Texture2D texture, int regionAmountX, int regionAmountY) : this(new TextureRegion(texture), regionAmountX, regionAmountY) {} private TextureRegion GetOrAddRegion(Rectangle rect) { if (this.regions.TryGetValue(rect, out var region)) return region; region = new TextureRegion(this.Region, rect.X * this.RegionWidth, rect.Y * this.RegionHeight, rect.Width * this.RegionWidth, rect.Height * this.RegionHeight); this.regions.Add(rect, region); return region; } } }