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);
}
}
}