From 4a8a55fde3f2d0eccb3948ce7667c828c77319b8 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 12 Nov 2021 18:12:57 +0100 Subject: [PATCH] allow removing items from a static sprite batch --- MLEM/Misc/StaticSpriteBatch.cs | 89 +++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/MLEM/Misc/StaticSpriteBatch.cs b/MLEM/Misc/StaticSpriteBatch.cs index 0049fe0..7def0ea 100644 --- a/MLEM/Misc/StaticSpriteBatch.cs +++ b/MLEM/Misc/StaticSpriteBatch.cs @@ -7,7 +7,7 @@ using MLEM.Extensions; namespace MLEM.Misc { /// /// A static sprite batch is a variation of that keeps all batched items in a , allowing for them to be drawn multiple times. - /// To add items to a static sprite batch, use to clear currently batched items, to begin batching, Add and its various overloads to add batch items and to end batching. + /// To add items to a static sprite batch, use to clear currently batched items, to begin batching, Add and its various overloads to add batch items, to remove them again, and to end batching. /// To draw the batched items, call . /// public class StaticSpriteBatch : IDisposable { @@ -62,7 +62,7 @@ namespace MLEM.Misc { throw new InvalidOperationException("Not batching"); this.batching = false; - // if we didn't add any batch items, we don't have to recalculate anything + // if we didn't add or remove any batch items, we don't have to recalculate anything if (!this.batchChanged) return; this.batchChanged = false; @@ -179,7 +179,8 @@ namespace MLEM.Misc { /// A scaling of this sprite. /// Modificators for drawing. Can be combined. /// A depth of the layer of this sprite. - public void Add(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) { + /// The that was created from the added data + public ItemInfo Add(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) { origin *= scale; Vector2 size, texTl, texBr; @@ -204,9 +205,9 @@ namespace MLEM.Misc { (texBr.X, texTl.X) = (texTl.X, texBr.X); if (rotation == 0) { - this.Add(texture, position - origin, size, color, texTl, texBr, layerDepth); + return this.Add(texture, position - origin, size, color, texTl, texBr, layerDepth); } else { - this.Add(texture, position, -origin, size, (float) Math.Sin(rotation), (float) Math.Cos(rotation), color, texTl, texBr, layerDepth); + return this.Add(texture, position, -origin, size, (float) Math.Sin(rotation), (float) Math.Cos(rotation), color, texTl, texBr, layerDepth); } } @@ -223,8 +224,9 @@ namespace MLEM.Misc { /// A scaling of this sprite. /// Modificators for drawing. Can be combined. /// A depth of the layer of this sprite. - public void Add(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) { - this.Add(texture, position, sourceRectangle, color, rotation, origin, new Vector2(scale), effects, layerDepth); + /// The that was created from the added data + public ItemInfo Add(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) { + return this.Add(texture, position, sourceRectangle, color, rotation, origin, new Vector2(scale), effects, layerDepth); } /// @@ -239,7 +241,8 @@ namespace MLEM.Misc { /// Center of the rotation. 0,0 by default. /// Modificators for drawing. Can be combined. /// A depth of the layer of this sprite. - public void Add(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth) { + /// The that was created from the added data + public ItemInfo Add(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth) { Vector2 texTl, texBr; if (sourceRectangle.HasValue) { var src = sourceRectangle.Value; @@ -262,9 +265,9 @@ namespace MLEM.Misc { (texBr.X, texTl.X) = (texTl.X, texBr.X); if (rotation == 0) { - this.Add(texture, destinationRectangle.Location.ToVector2() - origin, destinationRectangle.Size.ToVector2(), color, texTl, texBr, layerDepth); + return this.Add(texture, destinationRectangle.Location.ToVector2() - origin, destinationRectangle.Size.ToVector2(), color, texTl, texBr, layerDepth); } else { - this.Add(texture, destinationRectangle.Location.ToVector2(), -origin, destinationRectangle.Size.ToVector2(), (float) Math.Sin(rotation), (float) Math.Cos(rotation), color, texTl, texBr, layerDepth); + return this.Add(texture, destinationRectangle.Location.ToVector2(), -origin, destinationRectangle.Size.ToVector2(), (float) Math.Sin(rotation), (float) Math.Cos(rotation), color, texTl, texBr, layerDepth); } } @@ -276,8 +279,9 @@ namespace MLEM.Misc { /// The drawing location on screen. /// An optional region on the texture which will be rendered. If null - draws full texture. /// A color mask. - public void Add(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color) { - this.Add(texture, position, sourceRectangle, color, 0, Vector2.Zero, 1, SpriteEffects.None, 0); + /// The that was created from the added data + public ItemInfo Add(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color) { + return this.Add(texture, position, sourceRectangle, color, 0, Vector2.Zero, 1, SpriteEffects.None, 0); } /// @@ -288,8 +292,9 @@ namespace MLEM.Misc { /// The drawing bounds on screen. /// An optional region on the texture which will be rendered. If null - draws full texture. /// A color mask. - public void Add(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color) { - this.Add(texture, destinationRectangle, sourceRectangle, color, 0, Vector2.Zero, SpriteEffects.None, 0); + /// The that was created from the added data + public ItemInfo Add(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color) { + return this.Add(texture, destinationRectangle, sourceRectangle, color, 0, Vector2.Zero, SpriteEffects.None, 0); } /// @@ -299,8 +304,9 @@ namespace MLEM.Misc { /// A texture. /// The drawing location on screen. /// A color mask. - public void Add(Texture2D texture, Vector2 position, Color color) { - this.Add(texture, position, null, color); + /// The that was created from the added data + public ItemInfo Add(Texture2D texture, Vector2 position, Color color) { + return this.Add(texture, position, null, color); } /// @@ -310,8 +316,28 @@ namespace MLEM.Misc { /// A texture. /// The drawing bounds on screen. /// A color mask. - public void Add(Texture2D texture, Rectangle destinationRectangle, Color color) { - this.Add(texture, destinationRectangle, null, color); + /// The that was created from the added data + public ItemInfo Add(Texture2D texture, Rectangle destinationRectangle, Color color) { + return this.Add(texture, destinationRectangle, null, color); + } + + /// + /// Removes the given item from this batch. + /// Note that this batch needs to currently be batching, meaning has to have been called previously. + /// + /// The item to remove + /// Whether the item was successfully removed + /// Thrown if this method is called before was called + public bool Remove(ItemInfo item) { + if (!this.batching) + throw new InvalidOperationException("Not batching"); + var firstIndex = this.vertices.IndexOf(item.First); + if (firstIndex >= 0 && firstIndex + item.Count <= this.vertices.Count) { + this.vertices.RemoveRange(firstIndex, item.Count); + this.batchChanged = true; + return true; + } + return false; } /// @@ -323,23 +349,23 @@ namespace MLEM.Misc { GC.SuppressFinalize(this); } - private void Add(Texture2D texture, Vector2 pos, Vector2 offset, Vector2 size, float sin, float cos, Color color, Vector2 texTl, Vector2 texBr, float depth) { - this.Add(texture, + private ItemInfo Add(Texture2D texture, Vector2 pos, Vector2 offset, Vector2 size, float sin, float cos, Color color, Vector2 texTl, Vector2 texBr, float depth) { + return this.Add(texture, new VertexPositionColorTexture(new Vector3(pos.X + offset.X * cos - offset.Y * sin, pos.Y + offset.X * sin + offset.Y * cos, depth), color, texTl), new VertexPositionColorTexture(new Vector3(pos.X + (offset.X + size.X) * cos - offset.Y * sin, pos.Y + (offset.X + size.X) + offset.Y * cos, depth), color, new Vector2(texBr.X, texTl.Y)), new VertexPositionColorTexture(new Vector3(pos.X + offset.X * cos - (offset.Y + size.Y) * sin, pos.Y + offset.X * sin + (offset.Y + size.Y) * cos, depth), color, new Vector2(texTl.X, texBr.Y)), new VertexPositionColorTexture(new Vector3(pos.X + (offset.X + size.X) * cos - (offset.Y + size.Y) * sin, pos.Y + (offset.X + size.X) * sin + (offset.Y + size.Y) * cos, depth), color, texBr)); } - private void Add(Texture2D texture, Vector2 pos, Vector2 size, Color color, Vector2 texTl, Vector2 texBr, float depth) { - this.Add(texture, + private ItemInfo Add(Texture2D texture, Vector2 pos, Vector2 size, Color color, Vector2 texTl, Vector2 texBr, float depth) { + return this.Add(texture, new VertexPositionColorTexture(new Vector3(pos, depth), color, texTl), new VertexPositionColorTexture(new Vector3(pos.X + size.X, pos.Y, depth), color, new Vector2(texBr.X, texTl.Y)), new VertexPositionColorTexture(new Vector3(pos.X, pos.Y + size.Y, depth), color, new Vector2(texTl.X, texBr.Y)), new VertexPositionColorTexture(new Vector3(pos.X + size.X, pos.Y + size.Y, depth), color, texBr)); } - private void Add(Texture2D texture, VertexPositionColorTexture tl, VertexPositionColorTexture tr, VertexPositionColorTexture bl, VertexPositionColorTexture br) { + private ItemInfo Add(Texture2D texture, VertexPositionColorTexture tl, VertexPositionColorTexture tr, VertexPositionColorTexture bl, VertexPositionColorTexture br) { if (!this.batching) throw new InvalidOperationException("Not batching"); if (this.texture != null && this.texture != texture) @@ -350,6 +376,23 @@ namespace MLEM.Misc { this.vertices.Add(bl); this.vertices.Add(br); this.batchChanged = true; + return new ItemInfo(tl, 4); + } + + /// + /// A struct that represents an item added to a using Add or any of its overloads. + /// A returned can be removed using . + /// + public readonly struct ItemInfo { + + internal readonly VertexPositionColorTexture First; + internal readonly int Count; + + internal ItemInfo(VertexPositionColorTexture first, int count) { + this.First = first; + this.Count = count; + } + } }