2019-01-12 04:09:42 +00:00
using Microsoft.Xna.Framework ;
using Microsoft.Xna.Framework.Graphics ;
using RecrownedAthenaeum.Camera ;
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
namespace RecrownedAthenaeum.Render
{
public class PrimitiveBatch : IDisposable
{
2019-01-12 05:11:45 +00:00
List < VertexPositionColor > vertices ;
int maxVertices ;
2019-01-12 04:09:42 +00:00
int bufferPosition ;
BasicEffect basicEffect ;
PrimitiveType primitiveType ;
int verticesPerPrimitive ;
GraphicsDevice graphicsDevice ;
bool began ;
bool isDisposed ;
/// <summary>
/// Creates a batch used to draw primitives.
/// </summary>
/// <param name="graphicsDevice">The current graphics device being used.</param>
/// <param name="camera">The current camera being used.</param>
2019-01-12 05:11:45 +00:00
/// <param name="verticesPerBatch">The amount of vertices every batch can hold before flushing. Default is 450. Should be changed to be the most optimal number if possible. Especially if using strip primitive types.</param>
public PrimitiveBatch ( GraphicsDevice graphicsDevice , Camera2D camera , int verticesPerBatch = 500 )
2019-01-12 04:09:42 +00:00
{
this . graphicsDevice = graphicsDevice ? ? throw new ArgumentNullException ( "Graphics device can't be null." ) ;
2019-01-12 05:11:45 +00:00
maxVertices = verticesPerBatch ;
2019-01-12 04:09:42 +00:00
basicEffect = new BasicEffect ( graphicsDevice ) ;
basicEffect . VertexColorEnabled = true ;
basicEffect . View = camera . Matrix ;
2019-01-12 05:11:45 +00:00
vertices = new List < VertexPositionColor > ( verticesPerBatch ) ;
2019-01-12 04:09:42 +00:00
}
/// <summary>
/// Starts the batch. Batch cannot be started twice.
/// </summary>
/// <param name="primitiveType">The type of primitive this batch would be drawing.</param>
public void Begin ( PrimitiveType primitiveType )
{
if ( began ) throw new InvalidOperationException ( "Begin is being called twice before being ended." ) ;
this . primitiveType = primitiveType ;
2019-01-12 05:11:45 +00:00
verticesPerPrimitive = 0 ;
2019-01-12 04:09:42 +00:00
switch ( primitiveType )
{
case PrimitiveType . LineList : verticesPerPrimitive = 2 ; break ;
case PrimitiveType . TriangleList : verticesPerPrimitive = 3 ; break ;
2019-01-12 05:11:45 +00:00
default : verticesPerPrimitive = 1 ; break ;
2019-01-12 04:09:42 +00:00
}
basicEffect . CurrentTechnique . Passes [ 0 ] . Apply ( ) ;
began = true ;
}
/// <summary>
/// Ends the batch. Begin needs to be called before end.
/// </summary>
public void End ( )
{
if ( ! began ) throw new InvalidOperationException ( "Begin must be called before ending." ) ;
Flush ( ) ;
}
/// <summary>
/// Adds a vertex position for the primitive being drawn. The batch needs to have beens started before this.
/// </summary>
/// <param name="vertex">The vector that represents the vertex.</param>
/// <param name="color">The color of that vertex.</param>
public void AddVertex ( Vector2 vertex , Color color )
{
if ( ! began ) throw new InvalidOperationException ( "Begin needs to be called before adding vertex." ) ;
2019-01-12 05:11:45 +00:00
if ( primitiveType ! = PrimitiveType . LineStrip & & primitiveType ! = PrimitiveType . TriangleStrip & & bufferPosition + verticesPerPrimitive > = maxVertices & & ( bufferPosition % maxVertices = = 0 ) )
2019-01-12 04:09:42 +00:00
{
Flush ( ) ;
}
2019-01-12 05:11:45 +00:00
vertices [ bufferPosition ] = new VertexPositionColor ( new Vector3 ( vertex , 0 ) , color ) ;
2019-01-12 04:09:42 +00:00
bufferPosition + + ;
}
/// <summary>
2019-01-12 05:11:45 +00:00
/// Flushes the batch. Automatically called if required if using <see cref="PrimitiveType.LineList"/> or <see cref="PrimitiveType.TriangleList"/>. Otherwise, manual flushing is required.
2019-01-12 04:09:42 +00:00
/// </summary>
public void Flush ( )
{
if ( ! began ) throw new InvalidOperationException ( "Begin needs to be called before flushing." ) ;
if ( bufferPosition = = 0 ) return ;
2019-01-12 05:11:45 +00:00
graphicsDevice . DrawUserPrimitives ( primitiveType , vertices . ToArray ( ) , 0 , bufferPosition / verticesPerPrimitive ) ;
2019-01-12 04:09:42 +00:00
bufferPosition = 0 ;
}
public void Dispose ( )
{
Dispose ( true ) ;
GC . SuppressFinalize ( this ) ;
}
public void Dispose ( bool disposing )
{
if ( disposing & & ! isDisposed )
{
basicEffect . Dispose ( ) ;
isDisposed = true ;
}
}
}
}