123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679 |
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Linq;
- using System.Numerics;
- using System.Text;
- using System.Threading.Tasks;
- namespace Veldrid.Common
- {
- /// <summary>
- /// A class for drawing sprites in one or more optimized batches.
- /// </summary>
- /// <typeparam name="TTexture">The texture type to renderer.</typeparam>
- public abstract class SpriteBatch<TTexture> : ISpriteBatch<TTexture> where TTexture : notnull, ITexture2D
- {
- /// <summary>
- /// The batcher with all entities to renderer.
- /// </summary>
- protected readonly Batcher<TTexture> _batcher;
- private bool _beginCalled;
- /// <summary>
- /// Creates a new <see cref="SpriteBatch{TTexture}"/>.
- /// </summary>
- public SpriteBatch()
- {
- _batcher = new Batcher<TTexture>();
- _beginCalled = false;
- IsDisposed = false;
- ResetScissor();
- }
- /// <summary>
- /// Deconstructor of <see cref="SpriteBatch{TTexture}"/>.
- /// </summary>
- ~SpriteBatch()
- {
- CoreDispose(false);
- }
- /// <summary>
- /// The view matrix to use to renderer.
- /// </summary>
- public Matrix4x4 ViewMatrix { get; set; }
- /// <inheritdoc/>
- public bool IsDisposed { get; protected set; }
- /// <inheritdoc/>
- public RectangleF Scissor { get; set; }
- /// <summary>
- /// Begins the sprite branch.
- /// </summary>
- /// <exception cref="InvalidOperationException">Thrown if <see cref="Begin"/> is called next time without previous <see cref="End"/>.</exception>
- public void Begin()
- {
- if (_beginCalled)
- throw new InvalidOperationException("Begin cannot be called again until End has been successfully called.");
- ViewMatrix = Matrix4x4.Identity;
- _beginCalled = true;
- _batcher.Clear();
- }
- /// <summary>
- /// Flushes all batched text and sprites to the screen.
- /// </summary>
- /// <exception cref="InvalidOperationException">This command should be called after <see cref="Begin"/> and drawing commands.</exception>
- public void End()
- {
- if (!_beginCalled)
- throw new InvalidOperationException("Begin must be called before calling End.");
- _beginCalled = false;
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture, RectangleF destinationRectangle, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, SpriteOptions options, float layerDepth) =>
- Draw(SpriteBatch<TTexture>.Cast(texture), destinationRectangle, sourceRectangle, color, rotation, origin, options, layerDepth);
- /// <inheritdoc/>
- public void Draw(ITexture2D texture, PointF position, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteOptions options, float layerDepth) =>
- Draw(SpriteBatch<TTexture>.Cast(texture), position, sourceRectangle, color, rotation, origin, scale, options, layerDepth);
- /// <inheritdoc/>
- public void Draw(TTexture texture, RectangleF destinationRectangle, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, SpriteOptions options, float layerDepth)
- {
- CheckValid(texture);
- ref var item = ref _batcher.Add(texture);
- var size =new Vector2(texture.Size.Width,texture.Size.Height);
- item = new BatchItem(size, destinationRectangle, sourceRectangle, color, rotation, origin, layerDepth, Transform(Scissor, ViewMatrix), options);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture, PointF position, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteOptions options, float layerDepth)
- {
- CheckValid(texture);
- ref var item = ref _batcher.Add(texture);
- var size = new Vector2(texture.Size.Width, texture.Size.Height);
- item = new BatchItem(size, position, sourceRectangle, color, rotation, origin, scale, layerDepth, Transform(Scissor, ViewMatrix), options);
- }
- /// <inheritdoc/>
- public void Dispose()
- {
- CoreDispose(true);
- GC.SuppressFinalize(this);
- }
- private void CoreDispose(bool disposing)
- {
- if (IsDisposed)
- return;
- IsDisposed = true;
- Dispose(disposing);
- }
- /// <summary>
- /// Disposes resources.
- /// </summary>
- /// <param name="disposing">If called by <see cref="Dispose()"/></param>
- protected abstract void Dispose(bool disposing);
- private void CheckValid(ITexture2D texture)
- {
- if (texture == null)
- throw new ArgumentNullException(nameof(texture));
- if (!_beginCalled)
- throw new InvalidOperationException("Draw was called, but Begin has not yet been called. Begin must be called successfully before you can call Draw.");
- }
- private static TTexture Cast(ITexture2D texture)
- {
- if (texture is TTexture tt)
- return tt;
- throw new InvalidCastException($"The {texture} is not supported by this implementation.");
- }
- /// <inheritdoc/>
- public void ResetScissor()
- {
- const float v = 1 << 23;
- const float s = -(1 << 22);
- Scissor = new RectangleF(s, s, v, v);
- }
- /// <inheritdoc/>
- public void IntersectScissor(RectangleF clip)
- {
- var scissor = Scissor;
- scissor.Intersect(clip);
- Scissor = scissor;
- }
- private static RectangleF Transform(RectangleF rect, Matrix4x4 matrix)
- {
- var pos = Vector4.Transform(new Vector4(rect.X, rect.Y, 0, 1), matrix);
- var size = Vector4.Transform(new Vector4(rect.X + rect.Width, rect.Y + rect.Height, 0, 1), matrix);
- return new RectangleF(pos.X, pos.Y, size.X - pos.X, size.Y - pos.Y);
- }
- #region ISpriteBatch
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- RectangleF destinationRectangle,
- RectangleF sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- float layerDepth)
- {
- Draw(texture, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- RectangleF sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- Vector2 scale,
- float layerDepth)
- {
- Draw(texture, position, sourceRectangle, color, rotation, origin, scale, SpriteOptions.None, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- RectangleF destinationRectangle,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- SpriteOptions options,
- float layerDepth)
- {
- var srcRect = sourceRectangle ?? new RectangleF(0, 0, texture.Size.Width, texture.Size.Height);
- Draw(texture, destinationRectangle, srcRect, color, rotation, origin, options, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- RectangleF destinationRectangle,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- float layerDepth)
- {
- Draw(texture, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- Vector2 scale,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle ?? new RectangleF()
- {
- X = 0,
- Y = 0,
- Width = texture.Size.Width,
- Height = texture.Size.Height,
- },
- color: color,
- rotation: rotation,
- origin: origin,
- scale: scale,
- options: options,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- Vector2 scale,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle,
- color: color,
- rotation: rotation,
- origin: origin,
- scale: scale,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- float scale,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle,
- color: color,
- rotation: rotation,
- origin: origin,
- scale: new Vector2(scale),
- options: options,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- float scale,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle,
- color: color,
- rotation: rotation,
- origin: origin,
- scale: scale,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle,
- color: color,
- rotation: 0f,
- origin: default,
- scale: 0f,
- options: options,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle,
- color: color,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- RectangleF destinationRectangle,
- RectangleF? sourceRectangle,
- Color color,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture: texture,
- destinationRectangle: destinationRectangle,
- sourceRectangle: sourceRectangle,
- color: color,
- rotation: 0,
- origin: default,
- options: options,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,RectangleF destinationRectangle,
- RectangleF? sourceRectangle,
- Color color,
- float layerDepth)
- {
- Draw(texture: texture,
- destinationRectangle:destinationRectangle,
- sourceRectangle: sourceRectangle,
- color: color,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- Color color,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: new RectangleF(default, texture.Size),
- color: color,
- rotation: 0,
- origin: default,
- scale: default,
- options: options,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- PointF position,
- Color color,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- color: color,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- RectangleF destinationRectangle,
- Color color,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture: texture,
- destinationRectangle: destinationRectangle,
- sourceRectangle: new RectangleF(default, texture.Size),
- color: color,
- rotation: 0,
- origin: default,
- options: options,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(ITexture2D texture,
- RectangleF destinationRectangle,
- Color color,
- float layerDepth)
- {
- Draw(texture: texture,
- destinationRectangle: destinationRectangle,
- color: color,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- #endregion
- #region ISpriteBatch<TTexture>
-
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- RectangleF destinationRectangle,
- RectangleF sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- float layerDepth)
- {
- Draw(texture: texture,
- destinationRectangle: destinationRectangle,
- sourceRectangle: sourceRectangle,
- color: color,
- rotation: rotation,
- origin: origin,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- RectangleF sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- Vector2 scale,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle,
- color: color,
- rotation: rotation,
- origin: origin,
- scale: scale,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- RectangleF destinationRectangle,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- SpriteOptions options,
- float layerDepth)
- {
- //var srcRect = sourceRectangleF ?? new(0, 0, texture.Size.Width, texture.Size.Height);
- Draw(texture: texture,
- destinationRectangle: destinationRectangle,
- sourceRectangle: sourceRectangle ?? new RectangleF()
- {
- X = 0,
- Y = 0,
- Width = texture.Size.Width,
- Height = texture.Size.Height,
- },
- color: color,
- rotation: rotation,
- origin: origin,
- options: options,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- RectangleF destinationRectangle,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- float layerDepth)
- {
- Draw(texture, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- Vector2 scale,
- SpriteOptions options,
- float layerDepth)
- {
- //var srcRect = sourceRectangleF ?? new(0, 0, texture.Size.Width, texture.Size.Height);
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle ?? new RectangleF()
- {
- X = 0,
- Y = 0,
- Width = texture.Size.Width,
- Height = texture.Size.Height,
- },
- color: color,
- rotation: rotation,
- origin: origin,
- scale: scale,
- options: options,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- Vector2 scale,
- float layerDepth)
- {
- Draw(texture: texture,
- position: position,
- sourceRectangle: sourceRectangle,
- color: color,
- rotation: rotation,
- origin: origin,
- scale: scale,
- options: SpriteOptions.None,
- layerDepth: layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- float scale,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture, position, sourceRectangle, color, rotation, origin, new Vector2(scale), options, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float rotation,
- Vector2 origin,
- float scale,
- float layerDepth)
- {
- Draw(texture, position, sourceRectangle, color, rotation, origin, scale, SpriteOptions.None, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture, position, sourceRectangle, color, 0f, default, 0f, options, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- RectangleF? sourceRectangle,
- Color color,
- float layerDepth)
- {
- Draw(texture, position, sourceRectangle, color, SpriteOptions.None, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- RectangleF destinationRectangle,
- RectangleF? sourceRectangle,
- Color color,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture, destinationRectangle, sourceRectangle, color, 0, default, options, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- RectangleF destinationRectangle,
- RectangleF? sourceRectangle,
- Color color,
- float layerDepth)
- {
- Draw(texture, destinationRectangle, sourceRectangle, color, SpriteOptions.None, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- Color color,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture, position, new System.Drawing.Rectangle(default,texture.Size), color, 0, default, default, options, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- PointF position,
- Color color,
- float layerDepth)
- {
- Draw(texture, position, new System.Drawing.Rectangle(default,texture.Size), color, 0, default, default, SpriteOptions.None, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- RectangleF destinationRectangle,
- Color color,
- SpriteOptions options,
- float layerDepth)
- {
- Draw(texture, destinationRectangle, new System.Drawing.Rectangle(default, texture.Size), color, 0, default, options, layerDepth);
- }
- /// <inheritdoc/>
- public void Draw(TTexture texture,
- RectangleF destinationRectangle,
- Color color,
- float layerDepth)
- {
- Draw(texture, destinationRectangle, color, SpriteOptions.None, layerDepth);
- }
- #endregion
- }
- }
|