public static void SetAtlasPath(this MTexture self, string path) => ((patch_MTexture)self).SetAtlasPath(path);
// Patching constructors is ugly. public extern void orig_ctor_MTexture(MTexture parent, int x, int y, int width, int height);
public extern void orig_ctor_MTexture(MTexture parent, string atlasPath, Rectangle clipRect, Vector2 drawOffset, int width, int height);
public MTextureParent(MTexture inner) { Parent = inner; }
public void Ingest(ModAsset asset) { if (asset == null) { return; } // Crawl through all child assets. if (asset.Type == typeof(AssetTypeDirectory)) { lock (asset.Children) { foreach (ModAsset child in asset.Children) { Ingest(child); } } return; } // Forcibly add the mod content to the atlas. if (asset.Type != typeof(Texture2D)) { return; } string path = asset.PathVirtual; if (!path.StartsWith(RelativeDataPath)) { return; } path = path.Substring(RelativeDataPath.Length); if (textures.TryGetValue(path, out MTexture mtex)) { Logger.Log(LogLevel.Verbose, "Atlas.Ingest", $"{Path.GetFileName(DataPath)} + ({asset.Source?.Name ?? "???"}) {path}"); mtex.SetOverride(asset); this[path] = mtex; return; } VirtualTexture vtex; try { vtex = VirtualContentExt.CreateTexture(asset); } catch { // The game is going to crash from this. Log the offending texture to make debugging easier. Logger.Log(LogLevel.Verbose, "Atlas.Ingest", $"Error while loading texture {path} ({asset.Source?.Name ?? "???"}) into atlas {Path.GetFileName(DataPath)}"); throw; } MTextureMeta meta = asset.GetMeta <MTextureMeta>(); if (meta != null) { // Apply width and height from meta. if (meta.Width == 0) { meta.Width = vtex.Width; } if (meta.Height == 0) { meta.Height = vtex.Height; } mtex = new MTexture(vtex, new Vector2(meta.X, meta.Y), meta.Width, meta.Height); } else { // Apply width and height from replacement texture. mtex = new MTexture(vtex); } mtex.AtlasPath = path; mtex.SetAtlas(this); mtex.SetOverride(asset); this[path] = mtex; }
public static MTextureOverlay AddOverlay(this MTexture self, VirtualTexture texture) => ((patch_MTexture)self).AddOverlay(texture);
public static void Ingest(this Atlas self, AssetMetadata asset) { Logger.Log("Atlas.Ingest", $"{self.GetDataPath()} + {asset.PathRelative}"); // Crawl through all child assets. if (asset.AssetType == typeof(AssetTypeDirectory)) { foreach (AssetMetadata child in asset.Children) { self.Ingest(child); } return; } // Forcibly add the mod content to the atlas. if (asset.AssetType == typeof(Texture2D)) { string parentPath = self.GetDataPath(); if (parentPath.StartsWith(Everest.Content.PathContentOrig)) { parentPath = parentPath.Substring(Everest.Content.PathContentOrig.Length + 1); } parentPath = parentPath.Replace('\\', '/'); string path = asset.PathRelative; if (!path.StartsWith(parentPath)) { return; } path = path.Substring(parentPath.Length + 1); VirtualTexture replacementV = VirtualContentExt.CreateTexture(asset); MTexture replacement; MTextureMeta meta = asset.GetMeta <MTextureMeta>(); Dictionary <string, MTexture> textures = self.GetTextures(); MTexture existing; if (textures.TryGetValue(path, out existing)) { // We're the currently active overlay. if (existing.Texture.GetMetadata() == asset) { return; } if (meta != null) { // Apply width and height from existing meta. existing.AddOverlay(replacementV, new Vector2(meta.X, meta.Y), meta.Width, meta.Height); } else { // Keep width and height from existing instance. existing.AddOverlay(replacementV, existing.DrawOffset, existing.Width, existing.Height); } replacement = existing; } else { if (meta != null) { // Apply width and height from existing meta. replacement = new MTexture(replacementV, new Vector2(meta.X, meta.Y), meta.Width, meta.Height); } else { // Apply width and height from replacement texture. replacement = new MTexture(replacementV); } // TODO: What's with the AtlasPath? Seems to stem from an atlas metadata property... } self[path] = replacement; return; } }
/// <summary> /// Sets the parent texture of the given MTexture. /// </summary> public static void SetParent(this MTexture self, MTexture parent) => ((patch_MTexture)self).Parent = parent;
internal Image(MTexture texture, bool active) : base(active) { Texture = texture; }
/// <summary> /// Add a new override layer. /// </summary> public static MTextureOverride AddOverride(this MTexture self, MTextureOverride layer) => ((patch_MTexture)self).AddOverride(layer);
/// <summary> /// Gets the parent texture of the given MTexture. /// </summary> public static MTexture GetParent(this MTexture self) => ((patch_MTexture)self).Parent;
/// <summary> /// Get the currently active meta override. /// </summary> public static MTextureOverride GetOverrideMeta(this MTexture self) => ((patch_MTexture)self).OverrideMeta;
public MTexture(MTexture parent, Rectangle clipRect) : this(parent, clipRect.X, clipRect.Y, clipRect.Width, clipRect.Height) { }
public MTexture(MTexture parent, string atlasPath, Rectangle clipRect) : this(parent, clipRect) { AtlasPath = atlasPath; }
public static MTextureOverlay GetOverlayMeta(this MTexture self) => ((patch_MTexture)self).OverlayMeta;
public Image(MTexture texture) : base(false) { Texture = texture; }
public static MTextureOverlay AddOverlay(this MTexture self, MTextureOverlay overlay) => ((patch_MTexture)self).AddOverlay(overlay);
/// <summary> /// Feed the given ModAsset into the atlas. /// </summary> public static void Ingest(this Atlas atlas, ModAsset asset) { if (asset == null) { return; } // Crawl through all child assets. if (asset.Type == typeof(AssetTypeDirectory)) { lock (asset.Children) { foreach (ModAsset child in asset.Children) { atlas.Ingest(child); } } return; } // Forcibly add the mod content to the atlas. if (asset.Type != typeof(Texture2D)) { return; } string parentPath = atlas.GetDataPath(); if (parentPath.StartsWith(Everest.Content.PathContentOrig)) { parentPath = parentPath.Substring(Everest.Content.PathContentOrig.Length + 1); } parentPath = parentPath.Replace('\\', '/'); string path = asset.PathVirtual; if (!path.StartsWith(parentPath + "/")) { return; } path = path.Substring(parentPath.Length + 1); Logger.Log(LogLevel.Verbose, "Atlas.Ingest", $"{Path.GetFileName(atlas.GetDataPath())} + ({asset.Source?.Name ?? "???"}) {path}"); MTexture mtex; Dictionary <string, MTexture> textures = atlas.GetTextures(); if (textures.TryGetValue(path, out mtex)) { mtex.SetOverride(asset); } else { VirtualTexture vtex = VirtualContentExt.CreateTexture(asset); MTextureMeta meta = asset.GetMeta <MTextureMeta>(); if (meta != null) { // Apply width and height from meta. if (meta.Width == 0) { meta.Width = vtex.Width; } if (meta.Height == 0) { meta.Height = vtex.Height; } mtex = new MTexture(vtex, new Vector2(meta.X, meta.Y), meta.Width, meta.Height); } else { // Apply width and height from replacement texture. mtex = new MTexture(vtex); } mtex.AtlasPath = path; mtex.SetAtlas(atlas); mtex.SetOverride(asset); } atlas.ResetCaches(); atlas[path] = mtex; }
public static MTextureOverlay AddOverlay(this MTexture self, VirtualTexture texture, Vector2 drawOffset, int frameWidth, int frameHeight) => ((patch_MTexture)self).AddOverlay(texture, drawOffset, frameWidth, frameHeight);
private static void ReadAtlasData(Atlas _atlas, string path, AtlasDataFormat format) { patch_Atlas atlas = (patch_Atlas)_atlas; string pathFull = Path.Combine(Engine.ContentDirectory, path); XmlDocument xmlDoc; VirtualTexture texV; MTexture texM; switch (format) { case AtlasDataFormat.TexturePacker_Sparrow: xmlDoc = Calc.LoadContentXML(path); XmlElement xmlTextureAtlas = xmlDoc["TextureAtlas"]; if (xmlTextureAtlas == null) { break; } texV = VirtualContent.CreateTexture(Path.Combine(Path.GetDirectoryName(path), xmlTextureAtlas.Attr("imagePath", ""))); texM = new MTexture(texV); texM.SetAtlas(atlas); atlas.Sources.Add(texV); XmlNodeList xmlSubs = xmlTextureAtlas.GetElementsByTagName("SubTexture"); foreach (XmlElement xmlSub in xmlSubs) { string name = xmlSub.Attr("name"); Rectangle clipRect = xmlSub.Rect(); if (xmlSub.HasAttr("frameX")) { atlas.textures[name] = new MTexture( texM, name, clipRect, new Vector2(-xmlSub.AttrInt("frameX"), -xmlSub.AttrInt("frameY")), xmlSub.AttrInt("frameWidth"), xmlSub.AttrInt("frameHeight") ); } else { atlas.textures[name] = new MTexture(texM, name, clipRect); } } break; case AtlasDataFormat.CrunchXml: if (!File.Exists(pathFull)) { break; } xmlDoc = Calc.LoadContentXML(path); XmlElement xmlAtlas = xmlDoc["atlas"]; foreach (XmlElement xmlAtlasSource in xmlAtlas) { texV = VirtualContent.CreateTexture(Path.Combine(Path.GetDirectoryName(path), xmlAtlasSource.Attr("n", "") + ".png")); texM = new MTexture(texV); texM.SetAtlas(atlas); atlas.Sources.Add(texV); foreach (XmlElement xmlSub in xmlAtlasSource) { string name = xmlSub.Attr("n"); Rectangle clipRect = new Rectangle(xmlSub.AttrInt("x"), xmlSub.AttrInt("y"), xmlSub.AttrInt("w"), xmlSub.AttrInt("h")); if (xmlSub.HasAttr("fx")) { atlas.textures[name] = new MTexture( texM, name, clipRect, new Vector2(-xmlSub.AttrInt("fx"), -xmlSub.AttrInt("fy")), xmlSub.AttrInt("fw"), xmlSub.AttrInt("fh") ); } else { atlas.textures[name] = new MTexture(texM, name, clipRect); } } } break; case AtlasDataFormat.CrunchBinary: if (!File.Exists(pathFull)) { break; } using (FileStream stream = File.OpenRead(pathFull)) using (BinaryReader reader = new BinaryReader(stream)) { short sources = reader.ReadInt16(); for (int i = 0; i < sources; i++) { texV = VirtualContent.CreateTexture(Path.Combine(Path.GetDirectoryName(path), reader.ReadNullTerminatedString() + ".png")); texM = new MTexture(texV); texM.SetAtlas(atlas); atlas.Sources.Add(texV); short subs = reader.ReadInt16(); for (int j = 0; j < subs; j++) { string name = reader.ReadNullTerminatedString(); short clipX = reader.ReadInt16(); short clipY = reader.ReadInt16(); short clipWidth = reader.ReadInt16(); short clipHeight = reader.ReadInt16(); short offsX = reader.ReadInt16(); short offsY = reader.ReadInt16(); short width = reader.ReadInt16(); short height = reader.ReadInt16(); atlas.textures[name] = new MTexture( texM, name, new Rectangle(clipX, clipY, clipWidth, clipHeight), new Vector2(-offsX, -offsY), width, height ); } } } break; case AtlasDataFormat.CrunchXmlOrBinary: if (File.Exists(pathFull + ".bin")) { ReadAtlasData(atlas, path + ".bin", AtlasDataFormat.CrunchBinary); } else if (File.Exists(pathFull + ".xml")) { ReadAtlasData(atlas, path + ".xml", AtlasDataFormat.CrunchXml); } return; case AtlasDataFormat.CrunchBinaryNoAtlas: if (!File.Exists(pathFull + ".bin")) { break; } using (FileStream stream = File.OpenRead(pathFull + ".bin")) using (BinaryReader reader = new BinaryReader(stream)) { short sources = reader.ReadInt16(); for (int i = 0; i < sources; i++) { string sourcePath = Path.Combine(Path.GetDirectoryName(path), reader.ReadNullTerminatedString()); short subs = reader.ReadInt16(); for (int j = 0; j < subs; j++) { string name = reader.ReadNullTerminatedString(); short unknownA = reader.ReadInt16(); short unknownB = reader.ReadInt16(); short unknownC = reader.ReadInt16(); short unknownD = reader.ReadInt16(); short offsX = reader.ReadInt16(); short offsY = reader.ReadInt16(); short width = reader.ReadInt16(); short height = reader.ReadInt16(); texV = VirtualContent.CreateTexture(Path.Combine(sourcePath, name + ".png")); texM = atlas.textures[name] = new MTexture(texV, new Vector2(-offsX, -offsY), width, height); texM.SetAtlas(atlas); atlas.Sources.Add(texV); } } } break; case AtlasDataFormat.Packer: if (!File.Exists(pathFull + ".meta")) { break; } using (FileStream stream = File.OpenRead(pathFull + ".meta")) using (BinaryReader reader = new BinaryReader(stream)) { reader.ReadInt32(); // ??? reader.ReadString(); // ??? reader.ReadInt32(); // ??? short sources = reader.ReadInt16(); for (int i = 0; i < sources; i++) { texV = VirtualContent.CreateTexture(Path.Combine(Path.GetDirectoryName(path), reader.ReadString() + ".data")); texM = new MTexture(texV); texM.SetAtlas(atlas); atlas.Sources.Add(texV); short subs = reader.ReadInt16(); for (int j = 0; j < subs; j++) { string name = reader.ReadString().Replace('\\', '/'); short clipX = reader.ReadInt16(); short clipY = reader.ReadInt16(); short clipWidth = reader.ReadInt16(); short clipHeight = reader.ReadInt16(); short offsX = reader.ReadInt16(); short offsY = reader.ReadInt16(); short width = reader.ReadInt16(); short height = reader.ReadInt16(); atlas.textures[name] = new MTexture( texM, name, new Rectangle(clipX, clipY, clipWidth, clipHeight), new Vector2(-offsX, -offsY), width, height ); } } if (stream.Position < stream.Length && reader.ReadString() == "LINKS") { short count = reader.ReadInt16(); for (int i = 0; i < count; i++) { string key = reader.ReadString(); string value = reader.ReadString(); atlas.links.Add(key, value); } } } break; case AtlasDataFormat.PackerNoAtlas: if (!File.Exists(pathFull + ".meta")) { break; } using (FileStream stream = File.OpenRead(pathFull + ".meta")) using (BinaryReader reader = new BinaryReader(stream)) { reader.ReadInt32(); reader.ReadString(); reader.ReadInt32(); short sources = reader.ReadInt16(); for (int i = 0; i < sources; i++) { string sourcePath = Path.Combine(Path.GetDirectoryName(path), reader.ReadString()); short subs = reader.ReadInt16(); for (int j = 0; j < subs; j++) { string name = reader.ReadString().Replace('\\', '/'); short unknownA = reader.ReadInt16(); short unknownB = reader.ReadInt16(); short unknownC = reader.ReadInt16(); short unknownD = reader.ReadInt16(); short offsX = reader.ReadInt16(); short offsY = reader.ReadInt16(); short width = reader.ReadInt16(); short height = reader.ReadInt16(); texV = VirtualContent.CreateTexture(Path.Combine(sourcePath, name + ".data")); texM = atlas.textures[name] = new MTexture(texV, new Vector2(-offsX, -offsY), width, height); texM.SetAtlas(atlas); texM.AtlasPath = name; atlas.Sources.Add(texV); } } if (stream.Position < stream.Length && reader.ReadString() == "LINKS") { short count = reader.ReadInt16(); for (int i = 0; i < count; i++) { string key = reader.ReadString(); string value = reader.ReadString(); atlas.links.Add(key, value); } } } break; default: break; } }
private static void ReadAtlasData(Atlas atlas, string path, AtlasDataFormat format) { switch (format) { case AtlasDataFormat.TexturePacker_Sparrow: { XmlDocument xml = Calc.LoadContentXML(path); XmlElement at = xml["TextureAtlas"]; var texturePath = at.Attr("imagePath", ""); var filename = Path.Combine(Engine.ContentDirectory, Path.Combine(Path.GetDirectoryName(path)), texturePath + ".png"); var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read); var texture = Texture2D.FromStream(Engine.Instance.GraphicsDevice, fileStream); fileStream.Close(); var mTexture = new MTexture(texture); atlas.Sources.Add(texture); var subtextures = at.GetElementsByTagName("SubTexture"); foreach (XmlElement sub in subtextures) { var name = sub.Attr("name"); var clipRect = sub.Rect(); if (sub.HasAttr("frameX")) { atlas.textures[name] = new MTexture(mTexture, name, clipRect, new Vector2(-sub.AttrInt("frameX"), -sub.AttrInt("frameY")), sub.AttrInt("frameWidth"), sub.AttrInt("frameHeight")); } else { atlas.textures[name] = new MTexture(mTexture, name, clipRect); } } } break; case AtlasDataFormat.CrunchXml: { XmlDocument xml = Calc.LoadContentXML(path); XmlElement at = xml["atlas"]; foreach (XmlElement tex in at) { var texturePath = tex.Attr("n", ""); var filename = Path.Combine(Engine.ContentDirectory, Path.Combine(Path.GetDirectoryName(path)), texturePath + ".png"); var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read); var texture = Texture2D.FromStream(Engine.Instance.GraphicsDevice, fileStream); fileStream.Close(); var mTexture = new MTexture(texture, filename); atlas.Sources.Add(texture); foreach (XmlElement sub in tex) { var name = sub.Attr("n"); var clipRect = new Rectangle(sub.AttrInt("x"), sub.AttrInt("y"), sub.AttrInt("w"), sub.AttrInt("h")); if (sub.HasAttr("fx")) { atlas.textures[name] = new MTexture(mTexture, name, clipRect, new Vector2(-sub.AttrInt("fx"), -sub.AttrInt("fy")), sub.AttrInt("fw"), sub.AttrInt("fh")); } else { atlas.textures[name] = new MTexture(mTexture, name, clipRect); } } } } break; case AtlasDataFormat.CrunchBinary: using (var stream = File.OpenRead(Path.Combine(Engine.ContentDirectory, path))) { var reader = new BinaryReader(stream); var textures = reader.ReadInt16(); for (int i = 0; i < textures; i++) { var textureName = reader.ReadNullTerminatedString(); var filename = Path.Combine(Engine.ContentDirectory, Path.Combine(Path.GetDirectoryName(path)), textureName + ".png"); var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read); var texture = Texture2D.FromStream(Engine.Instance.GraphicsDevice, fileStream); fileStream.Close(); atlas.Sources.Add(texture); var mTexture = new MTexture(texture, filename); var subtextures = reader.ReadInt16(); for (int j = 0; j < subtextures; j++) { var name = reader.ReadNullTerminatedString(); var x = reader.ReadInt16(); var y = reader.ReadInt16(); var w = reader.ReadInt16(); var h = reader.ReadInt16(); var fx = reader.ReadInt16(); var fy = reader.ReadInt16(); var fw = reader.ReadInt16(); var fh = reader.ReadInt16(); atlas.textures[name] = new MTexture(mTexture, name, new Rectangle(x, y, w, h), new Vector2(-fx, -fy), fw, fh); } } } break; case AtlasDataFormat.CrunchBinaryNoAtlas: using (var stream = File.OpenRead(Path.Combine(Engine.ContentDirectory, path + ".bin"))) { var reader = new BinaryReader(stream); var folders = reader.ReadInt16(); for (int i = 0; i < folders; i++) { var folderName = reader.ReadNullTerminatedString(); var folderPath = Path.Combine(Path.GetDirectoryName(path), folderName); var subtextures = reader.ReadInt16(); for (int j = 0; j < subtextures; j++) { var name = reader.ReadNullTerminatedString(); var x = reader.ReadInt16(); var y = reader.ReadInt16(); var w = reader.ReadInt16(); var h = reader.ReadInt16(); var fx = reader.ReadInt16(); var fy = reader.ReadInt16(); var fw = reader.ReadInt16(); var fh = reader.ReadInt16(); var filename = Path.Combine(folderPath, name + ".png"); var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read); var texture = Texture2D.FromStream(Engine.Instance.GraphicsDevice, fileStream); fileStream.Close(); atlas.Sources.Add(texture); atlas.textures[name] = new MTexture(texture, new Vector2(-fx, -fy), fw, fh, filename); } } } break; case AtlasDataFormat.Packer: using (var stream = File.OpenRead(Path.Combine(Engine.ContentDirectory, path + ".meta"))) { var reader = new BinaryReader(stream); reader.ReadInt32(); // version reader.ReadString(); // args reader.ReadInt32(); // hash var textures = reader.ReadInt16(); for (int i = 0; i < textures; i++) { var textureName = reader.ReadString(); var texturePath = Path.Combine(Path.GetDirectoryName(path), textureName + ".data"); var fileStream = new FileStream(texturePath, FileMode.Open, FileAccess.Read); var texture = Texture2D.FromStream(Engine.Instance.GraphicsDevice, fileStream); fileStream.Close(); atlas.Sources.Add(texture); var mTexture = new MTexture(texture); var subtextures = reader.ReadInt16(); for (int j = 0; j < subtextures; j++) { var name = reader.ReadString().Replace('\\', '/'); var x = reader.ReadInt16(); var y = reader.ReadInt16(); var w = reader.ReadInt16(); var h = reader.ReadInt16(); var fx = reader.ReadInt16(); var fy = reader.ReadInt16(); var fw = reader.ReadInt16(); var fh = reader.ReadInt16(); atlas.textures[name] = new MTexture(mTexture, name, new Rectangle(x, y, w, h), new Vector2(-fx, -fy), fw, fh); } } } break; case AtlasDataFormat.PackerNoAtlas: using (var stream = File.OpenRead(Path.Combine(Engine.ContentDirectory, path + ".meta"))) { var reader = new BinaryReader(stream); reader.ReadInt32(); // version reader.ReadString(); // args reader.ReadInt32(); // hash var folders = reader.ReadInt16(); for (int i = 0; i < folders; i++) { var folderName = reader.ReadString(); var folderPath = Path.Combine(Path.GetDirectoryName(path), folderName); var subtextures = reader.ReadInt16(); for (int j = 0; j < subtextures; j++) { var name = reader.ReadString().Replace('\\', '/'); var x = reader.ReadInt16(); var y = reader.ReadInt16(); var w = reader.ReadInt16(); var h = reader.ReadInt16(); var fx = reader.ReadInt16(); var fy = reader.ReadInt16(); var fw = reader.ReadInt16(); var fh = reader.ReadInt16(); var fileStream = new FileStream(Path.Combine(folderPath, name + ".data"), FileMode.Open, FileAccess.Read); var texture = Texture2D.FromStream(Engine.Instance.GraphicsDevice, fileStream); fileStream.Close(); atlas.Sources.Add(texture); atlas.textures[name] = new MTexture(texture, new Vector2(-fx, -fy), fw, fh); } } } break; case AtlasDataFormat.CrunchXmlOrBinary: if (File.Exists(Path.Combine(Engine.ContentDirectory, path + ".bin"))) { ReadAtlasData(atlas, path + ".bin", AtlasDataFormat.CrunchBinary); } else { ReadAtlasData(atlas, path + ".xml", AtlasDataFormat.CrunchXml); } break; default: throw new NotImplementedException(); } }
public SpriteData(MTexture atlas, string xmlPath) : this(atlas, Calc.LoadContentXML(xmlPath)) { }