using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text.RegularExpressions; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using MLEM.Textures; namespace MLEM.Data { /// /// This class represents an atlas of objects which are loaded from a special texture atlas file. /// To load a data texture atlas, you can use . /// To see the structure of a Data Texture Atlas, you can check out the sandbox project: . /// Additionally, if you are using Aseprite, there is a script to automatically populate it: /// public class DataTextureAtlas { /// /// The texture to use for this atlas /// public readonly Texture2D Texture; /// /// Returns the texture region with the given name, or null if it does not exist. /// /// The region's name public TextureRegion this[string name] { get { this.regions.TryGetValue(name, out var ret); return ret; } } /// /// Returns an enumerable of all of the s in this atlas. /// public IEnumerable Regions => this.regions.Values; private readonly Dictionary regions = new Dictionary(); /// /// Creates a new data texture atlas with the given texture and region amount. /// /// The texture to use for this atlas public DataTextureAtlas(Texture2D texture) { this.Texture = texture; } internal static DataTextureAtlas Load(ContentManager content, string texturePath, string infoPath, bool pivotRelative) { var info = new FileInfo(Path.Combine(content.RootDirectory, infoPath ?? $"{texturePath}.atlas")); string text; using (var reader = info.OpenText()) text = reader.ReadToEnd(); var texture = content.Load(texturePath); var atlas = new DataTextureAtlas(texture); // parse each texture region: " loc piv " const string regex = @"(.+)\W+loc\W+([0-9]+)\W+([0-9]+)\W+([0-9]+)\W+([0-9]+)\W+(?:piv\W+([0-9.]+)\W+([0-9.]+))?"; foreach (Match match in Regex.Matches(text, regex)) { var name = match.Groups[1].Value.Trim(); var loc = new Rectangle( int.Parse(match.Groups[2].Value), int.Parse(match.Groups[3].Value), int.Parse(match.Groups[4].Value), int.Parse(match.Groups[5].Value)); var piv = Vector2.Zero; if (match.Groups[6].Success) { piv = new Vector2( float.Parse(match.Groups[6].Value, CultureInfo.InvariantCulture) - (pivotRelative ? 0 : loc.X), float.Parse(match.Groups[7].Value, CultureInfo.InvariantCulture) - (pivotRelative ? 0 : loc.Y)); } atlas.regions.Add(name, new TextureRegion(texture, loc) { PivotPixels = piv, Name = name }); } return atlas; } } /// /// A set of extension methods for dealing with . /// public static class DataTextureAtlasExtensions { /// /// Loads a from the given texture and texture data file. /// /// The content manager to use for loading /// The path to the texture file /// The path, including extension, to the atlas info file, or null if ".atlas" should be used /// If this value is true, then the pivot points passed in the info file will be relative to the coordinates of the texture region, not relative to the entire texture's origin. /// A new data texture atlas with the given settings public static DataTextureAtlas LoadTextureAtlas(this ContentManager content, string texturePath, string infoPath = null, bool pivotRelative = false) { return DataTextureAtlas.Load(content, texturePath, infoPath, pivotRelative); } } }