From 5cb77be41027fbeefae30315a53be0bfd6a9ce34 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sat, 27 Nov 2021 14:27:56 +0100 Subject: [PATCH] Allow using StaticSpriteBatch for AutoTiling --- CHANGELOG.md | 1 + MLEM/Misc/AutoTiling.cs | 62 +++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fe2779..6473793 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Improvements - Exposed the epsilon value used by Camera - Added Padding.Empty - Throw an exception when text formatter macros resolve recursively too many times +- Allow using StaticSpriteBatch for AutoTiling Fixes - Fixed some end-of-line inconsistencies when using the Right text alignment diff --git a/MLEM/Misc/AutoTiling.cs b/MLEM/Misc/AutoTiling.cs index ff844ed..272f0f7 100644 --- a/MLEM/Misc/AutoTiling.cs +++ b/MLEM/Misc/AutoTiling.cs @@ -5,6 +5,7 @@ namespace MLEM.Misc { /// /// This class contains a method that allows users to easily draw a tile with automatic connections. /// For auto-tiling in this manner to work, auto-tiled textures have to be laid out in a format described in . + /// Note that can also be used for drawing by using the method instead. /// public static class AutoTiling { @@ -12,28 +13,51 @@ namespace MLEM.Misc { /// This method allows for a tiled texture to be drawn in an auto-tiling mode. /// This allows, for example, a grass patch on a tilemap to have nice looking edges that transfer over into a path without any hard edges between tiles. /// - /// For auto-tiling in this way to work, the tiles have to be laid out in a specific order. This order is shown in the auto-tiling demo's textures. + /// For auto-tiling in this way to work, the tiles have to be laid out as follows: five tiles aligned horizontally within the texture file, with the following information: + /// + /// The texture used for filling big areas + /// The texture used for straight, horizontal borders, with the borders facing away from the center + /// The texture used for outer corners, with the corners facing away from the center + /// The texture used for straight, vertical borders, with the borders facing away from the center + /// The texture used for inner corners, with the corners facing away from the center + /// /// For more information and an example, see https://github.com/Ellpeck/MLEM/blob/main/Demos/AutoTilingDemo.cs#L20-L28. /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static void DrawAutoTile(SpriteBatch batch, Vector2 pos, Texture2D texture, Rectangle textureRegion, ConnectsTo connectsTo, Color color, float rotation = 0, Vector2? origin = null, Vector2? scale = null, float layerDepth = 0) { - var org = origin ?? Vector2.Zero; + /// The sprite batch to use for drawing. + /// The position to draw at. + /// The texture to use for drawing. + /// The location of the first texture region, as described in the summary. + /// A function that determines whether two positions should connect. + /// The color to draw with. + /// The origin to draw from. + /// The scale to draw with. + /// The layer depth to draw with. + public static void DrawAutoTile(SpriteBatch batch, Vector2 pos, Texture2D texture, Rectangle textureRegion, ConnectsTo connectsTo, Color color, Vector2? origin = null, Vector2? scale = null, float layerDepth = 0) { + var orig = origin ?? Vector2.Zero; var sc = scale ?? Vector2.One; + var (p1, r1, p2, r2, p3, r3, p4, r4) = CalculateAutoTile(pos, textureRegion, connectsTo, sc); + batch.Draw(texture, p1, r1, color, 0, orig, sc, SpriteEffects.None, layerDepth); + batch.Draw(texture, p2, r2, color, 0, orig, sc, SpriteEffects.None, layerDepth); + batch.Draw(texture, p3, r3, color, 0, orig, sc, SpriteEffects.None, layerDepth); + batch.Draw(texture, p4, r4, color, 0, orig, sc, SpriteEffects.None, layerDepth); + } + /// + public static void AddAutoTile(StaticSpriteBatch batch, Vector2 pos, Texture2D texture, Rectangle textureRegion, ConnectsTo connectsTo, Color color, float rotation = 0, Vector2? origin = null, Vector2? scale = null, float layerDepth = 0) { + var orig = origin ?? Vector2.Zero; + var sc = scale ?? Vector2.One; + var (p1, r1, p2, r2, p3, r3, p4, r4) = CalculateAutoTile(pos, textureRegion, connectsTo, sc); + batch.Add(texture, p1, r1, color, 0, orig, sc, SpriteEffects.None, layerDepth); + batch.Add(texture, p2, r2, color, 0, orig, sc, SpriteEffects.None, layerDepth); + batch.Add(texture, p3, r3, color, 0, orig, sc, SpriteEffects.None, layerDepth); + batch.Add(texture, p4, r4, color, 0, orig, sc, SpriteEffects.None, layerDepth); + } + + private static (Vector2, Rectangle, Vector2, Rectangle, Vector2, Rectangle, Vector2, Rectangle) CalculateAutoTile(Vector2 pos, Rectangle textureRegion, ConnectsTo connectsTo, Vector2 scale) { var up = connectsTo(0, -1); var down = connectsTo(0, 1); var left = connectsTo(-1, 0); var right = connectsTo(1, 0); - var xUl = up && left ? connectsTo(-1, -1) ? 0 : 4 : left ? 1 : up ? 3 : 2; var xUr = up && right ? connectsTo(1, -1) ? 0 : 4 : right ? 1 : up ? 3 : 2; var xDl = down && left ? connectsTo(-1, 1) ? 0 : 4 : left ? 1 : down ? 3 : 2; @@ -41,10 +65,12 @@ namespace MLEM.Misc { var (w, h) = textureRegion.Size; var (w2, h2) = new Point(w / 2, h / 2); - batch.Draw(texture, new Vector2(pos.X, pos.Y), new Rectangle(textureRegion.X + 0 + xUl * w, textureRegion.Y + 0, w2, h2), color, rotation, org, sc, SpriteEffects.None, layerDepth); - batch.Draw(texture, new Vector2(pos.X + 0.5F * w * sc.X, pos.Y), new Rectangle(textureRegion.X + w2 + xUr * w, textureRegion.Y + 0, w2, h2), color, rotation, org, sc, SpriteEffects.None, layerDepth); - batch.Draw(texture, new Vector2(pos.X, pos.Y + 0.5F * h * sc.Y), new Rectangle(textureRegion.X + xDl * w, textureRegion.Y + h2, w2, h2), color, rotation, org, sc, SpriteEffects.None, layerDepth); - batch.Draw(texture, new Vector2(pos.X + 0.5F * w * sc.X, pos.Y + 0.5F * h * sc.Y), new Rectangle(textureRegion.X + w2 + xDr * w, textureRegion.Y + h2, w2, h2), color, rotation, org, sc, SpriteEffects.None, layerDepth); + + return ( + new Vector2(pos.X, pos.Y), new Rectangle(textureRegion.X + xUl * w, textureRegion.Y, w2, h2), + new Vector2(pos.X + w2 * scale.X, pos.Y), new Rectangle(textureRegion.X + w2 + xUr * w, textureRegion.Y, w2, h2), + new Vector2(pos.X, pos.Y + h2 * scale.Y), new Rectangle(textureRegion.X + xDl * w, textureRegion.Y + h2, w2, h2), + new Vector2(pos.X + w2 * scale.X, pos.Y + h2 * scale.Y), new Rectangle(textureRegion.X + w2 + xDr * w, textureRegion.Y + h2, w2, h2)); } ///