- Implemented the SkinnedEffect class (not tested yet, sample will come soon)

- Optimizations in the SpriteBatch and SpriteFont classes
This commit is contained in:
SND\AstrorEnales_cp 2012-09-11 13:51:20 +00:00
parent 8b735c16c2
commit 7350ca3d3a
10 changed files with 879 additions and 706 deletions

View File

@ -67,6 +67,8 @@ namespace ANX.Framework.Graphics
{ {
this.width = width; this.width = width;
this.height = height; this.height = height;
OneOverWidth = 1f / width;
OneOverHeight = 1f / height;
base.levelCount = 1; base.levelCount = 1;
base.format = SurfaceFormat.Color; base.format = SurfaceFormat.Color;

View File

@ -1,34 +1,189 @@
#region Using Statements
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.Graphics; using ANX.Framework.NonXNA.Development;
#endregion // Using Statements
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license // For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Graphics namespace ANX.Framework.Graphics
{ {
[PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.Untested)]
[Developer("AstrorEnales")]
public class SkinnedEffect : Effect, IEffectMatrices, IEffectLights, IEffectFog public class SkinnedEffect : Effect, IEffectMatrices, IEffectLights, IEffectFog
{ {
public const int MaxBones = 72;
#region Private
private Matrix world;
private Matrix view;
private Matrix projection;
private bool preferPerPixelLighting;
private bool isFogEnabled;
private Vector3 diffuseColor;
private Vector3 specularColor;
private Vector3 fogColor;
private Vector3 emissiveColor;
private Vector3 ambientLightColor;
private Matrix[] bones;
private int weightsPerBone;
#endregion
#region Public
public float FogEnd { get; set; }
public float FogStart { get; set; }
public Texture2D Texture { get; set; }
public float Alpha { get; set; }
public float SpecularPower { get; set; }
public DirectionalLight DirectionalLight0 { get; private set; }
public DirectionalLight DirectionalLight1 { get; private set; }
public DirectionalLight DirectionalLight2 { get; private set; }
public int WeightsPerVertex
{
get
{
return weightsPerBone;
}
set
{
if (value != 1 && value != 2 && value != 4)
throw new ArgumentOutOfRangeException("Weights per bone only allows 1, 2 or 4 as value!");
weightsPerBone = value;
}
}
public bool PreferPerPixelLighting
{
get { return preferPerPixelLighting; }
set
{
preferPerPixelLighting = value;
SelectTechnique();
}
}
public Matrix Projection
{
get { return projection; }
set { projection = value; }
}
public Matrix View
{
get { return view; }
set { view = value; }
}
public Matrix World
{
get { return world; }
set { world = value; }
}
public Vector3 AmbientLightColor
{
get { return ambientLightColor; }
set { ambientLightColor = value; }
}
public bool LightingEnabled
{
get { return true; }
set
{
if (value == false)
throw new NotSupportedException("SkinnedEffect without Lighting isn't supported!");
}
}
public Vector3 FogColor
{
get { return fogColor; }
set { fogColor = value; }
}
public bool FogEnabled
{
get { return isFogEnabled; }
set
{
isFogEnabled = value;
SelectTechnique();
}
}
public Vector3 DiffuseColor
{
get { return diffuseColor; }
set { diffuseColor = value; }
}
public Vector3 EmissiveColor
{
get { return emissiveColor; }
set { emissiveColor = value; }
}
public Vector3 SpecularColor
{
get { return specularColor; }
set { specularColor = value; }
}
#endregion
#region Constructor
public SkinnedEffect(GraphicsDevice graphics) public SkinnedEffect(GraphicsDevice graphics)
: base(graphics, GetByteCode(), GetSourceLanguage()) : base(graphics, GetByteCode(), GetSourceLanguage())
{ {
throw new NotImplementedException(); world = Matrix.Identity;
view = Matrix.Identity;
projection = Matrix.Identity;
FogStart = 0f;
FogEnd = 1f;
Alpha = 1f;
diffuseColor = Vector3.One;
ambientLightColor = Vector3.One;
emissiveColor = Vector3.One;
specularColor = Vector3.One;
SpecularPower = 16f;
WeightsPerVertex = 4;
CreateLights(null);
DirectionalLight0.Enabled = true;
bones = new Matrix[MaxBones];
for (int index = 0; index < MaxBones; index++)
bones[index] = Matrix.Identity;
SelectTechnique();
} }
protected SkinnedEffect(SkinnedEffect cloneSource) protected SkinnedEffect(SkinnedEffect cloneSource)
: base(cloneSource) : base(cloneSource)
{ {
throw new NotImplementedException(); world = cloneSource.world;
view = cloneSource.view;
projection = cloneSource.projection;
preferPerPixelLighting = cloneSource.preferPerPixelLighting;
isFogEnabled = cloneSource.isFogEnabled;
diffuseColor = cloneSource.diffuseColor;
specularColor = cloneSource.specularColor;
fogColor = cloneSource.fogColor;
emissiveColor = cloneSource.emissiveColor;
ambientLightColor = cloneSource.ambientLightColor;
FogEnd = cloneSource.FogEnd;
FogStart = cloneSource.FogStart;
Texture = cloneSource.Texture;
SpecularPower = cloneSource.SpecularPower;
Alpha = cloneSource.Alpha;
WeightsPerVertex = cloneSource.WeightsPerVertex;
for (int index = 0; index < MaxBones; index++)
bones[index] = cloneSource.bones[index];
CreateLights(cloneSource);
SelectTechnique();
} }
#endregion
#region GetByteCode #region GetByteCode
private static byte[] GetByteCode() private static byte[] GetByteCode()
@ -46,245 +201,186 @@ namespace ANX.Framework.Graphics
} }
#endregion #endregion
public override Effect Clone() #region Clone
public override Effect Clone()
{ {
return new SkinnedEffect(this); return new SkinnedEffect(this);
} }
#endregion
public const int MaxBones = 72; #region CreateLights
private void CreateLights(SkinnedEffect cloneSource)
{
DirectionalLight0 = new DirectionalLight(Parameters["DirLight0Direction"], Parameters["DirLight0DiffuseColor"],
null, (cloneSource != null) ? cloneSource.DirectionalLight0 : null);
DirectionalLight1 = new DirectionalLight(Parameters["DirLight1Direction"], Parameters["DirLight1DiffuseColor"],
null, (cloneSource != null) ? cloneSource.DirectionalLight1 : null);
DirectionalLight2 = new DirectionalLight(Parameters["DirLight2Direction"], Parameters["DirLight2DiffuseColor"],
null, (cloneSource != null) ? cloneSource.DirectionalLight2 : null);
}
#endregion
public bool PreferPerPixelLighting #region EnableDefaultLighting
{ public void EnableDefaultLighting()
get {
{ LightingEnabled = true;
throw new NotImplementedException(); ambientLightColor = new Vector3(0.05333332f, 0.09882354f, 0.1819608f);
}
set
{
throw new NotImplementedException();
}
}
public Matrix Projection DirectionalLight0.Direction = new Vector3(-0.5265408f, -0.5735765f, -0.6275069f);
{ DirectionalLight0.DiffuseColor = new Vector3(1f, 0.9607844f, 0.8078432f);
get DirectionalLight0.SpecularColor = DirectionalLight0.DiffuseColor;
{ DirectionalLight0.Enabled = true;
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Matrix View DirectionalLight1.Direction = new Vector3(0.7198464f, 0.3420201f, 0.6040227f);
{ DirectionalLight1.DiffuseColor = new Vector3(0.9647059f, 0.7607844f, 0.4078432f);
get DirectionalLight1.SpecularColor = Vector3.Zero;
{ DirectionalLight1.Enabled = true;
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Matrix World DirectionalLight2.Direction = new Vector3(0.4545195f, -0.7660444f, 0.4545195f);
{ DirectionalLight2.DiffuseColor = new Vector3(0.3231373f, 0.3607844f, 0.3937255f);
get DirectionalLight2.SpecularColor = DirectionalLight2.DiffuseColor;
{ DirectionalLight2.Enabled = true;
throw new NotImplementedException(); }
} #endregion
set
{
throw new NotImplementedException();
}
}
public void EnableDefaultLighting() #region GetBoneTransforms
{ public Matrix[] GetBoneTransforms(int count)
throw new NotImplementedException(); {
} if (count <= 0)
throw new ArgumentOutOfRangeException("count");
if (count > 72)
throw new ArgumentException("The maximum number of allowed bones for the SkinnedEffect is " + MaxBones + "!");
public Vector3 AmbientLightColor var result = new Matrix[MaxBones];
{ for (int index = 0; index < MaxBones; index++)
get {
{ result[index] = bones[index];
throw new NotImplementedException(); }
} return result;
set }
{ #endregion
throw new NotImplementedException();
}
}
public DirectionalLight DirectionalLight0 #region SetBoneTransforms
{ public void SetBoneTransforms(Matrix[] boneTransforms)
get { throw new NotImplementedException(); } {
} if (boneTransforms == null || boneTransforms.Length == 0)
throw new ArgumentNullException("boneTransforms");
public DirectionalLight DirectionalLight1 if (boneTransforms.Length > 72)
{ throw new ArgumentException("The maximum number of allowed bones for the SkinnedEffect is " + MaxBones + "!");
get { throw new NotImplementedException(); }
}
public DirectionalLight DirectionalLight2 for (int index = 0; index < MaxBones; index++)
{ bones[index] = index < boneTransforms.Length ? boneTransforms[index] : Matrix.Identity;
get { throw new NotImplementedException(); } }
} #endregion
public bool LightingEnabled #region PreBindSetParameters
{ internal override void PreBindSetParameters()
get {
{ Matrix worldView;
throw new NotImplementedException(); Matrix.Multiply(ref world, ref view, out worldView);
} Matrix wvp;
set Matrix.Multiply(ref worldView, ref projection, out wvp);
{ Parameters["WorldViewProj"].SetValue(wvp);
throw new NotImplementedException();
}
}
public Vector3 FogColor SetLightingMatrices();
{ SetMaterialColor();
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public bool FogEnabled Parameters["Bones"].SetValue(bones);
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public float FogEnd Parameters["FogColor"].SetValue(fogColor);
{ Parameters["SpecularPower"].SetValue(SpecularPower);
get Parameters["SpecularColor"].SetValue(specularColor);
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public float FogStart if (Texture != null)
{ Parameters["Texture"].SetValue(Texture);
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Texture2D Texture if (isFogEnabled)
{ SetFogVector(ref worldView);
get else
{ Parameters["FogVector"].SetValue(Vector4.Zero);
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public int WeightsPerVertex SelectTechnique();
{ }
get #endregion
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Vector3 DiffuseColor #region SelectTechnique
{ private void SelectTechnique()
get {
{ string name = "";
throw new NotImplementedException(); if (WeightsPerVertex == 1)
} name = "OneBone";
set else if (WeightsPerVertex == 2)
{ name = "TwoBones";
throw new NotImplementedException(); else if (WeightsPerVertex == 4)
} name = "FourBones";
}
public Vector3 EmissiveColor bool oneLight = DirectionalLight1.Enabled == false && DirectionalLight2.Enabled == false;
{ if (preferPerPixelLighting)
get name += "PixelLighting";
{ else if (oneLight)
throw new NotImplementedException(); name += "OneLight";
} else
set name += "VertexLighting";
{
throw new NotImplementedException();
}
}
public Vector3 SpecularColor if (isFogEnabled == false)
{ name += "NoFog";
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public float SpecularPower CurrentTechnique = Techniques[name];
{ }
get #endregion
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public float Alpha #region SetLightingMatrices
{ private void SetLightingMatrices()
get {
{ Matrix worldInverse;
throw new NotImplementedException(); Matrix.Invert(ref world, out worldInverse);
} Matrix worldInverseTranspose;
set Matrix.Transpose(ref worldInverse, out worldInverseTranspose);
{
throw new NotImplementedException();
}
}
public Matrix[] GetBoneTransforms(int count) Parameters["World"].SetValue(world);
{ Parameters["WorldInverseTranspose"].SetValue(worldInverseTranspose);
throw new NotImplementedException();
}
public void SetBoneTransforms(Matrix[] boneTransforms) Matrix viewInverse;
{ Matrix.Invert(ref view, out viewInverse);
throw new NotImplementedException(); Parameters["EyePosition"].SetValue(viewInverse.Translation);
} }
#endregion
#region SetMaterialColor
private void SetMaterialColor()
{
Vector4 diffuse;
diffuse.X = diffuseColor.X * Alpha;
diffuse.Y = diffuseColor.Y * Alpha;
diffuse.Z = diffuseColor.Z * Alpha;
diffuse.W = Alpha;
Vector3 emissive;
emissive.X = (emissiveColor.X + ambientLightColor.X * diffuseColor.X) * Alpha;
emissive.Y = (emissiveColor.Y + ambientLightColor.Y * diffuseColor.Y) * Alpha;
emissive.Z = (emissiveColor.Z + ambientLightColor.Z * diffuseColor.Z) * Alpha;
Parameters["DiffuseColor"].SetValue(diffuse);
Parameters["EmissiveColor"].SetValue(emissive);
}
#endregion
#region SetFogVector
private void SetFogVector(ref Matrix worldView)
{
if (FogStart == FogEnd)
{
Parameters["FogVector"].SetValue(new Vector4(0f, 0f, 0f, 1f));
return;
}
float fogFactor = 1f / (FogStart - FogEnd);
Vector4 value;
value.X = worldView.M13 * fogFactor;
value.Y = worldView.M23 * fogFactor;
value.Z = worldView.M33 * fogFactor;
value.W = (worldView.M43 + FogStart) * fogFactor;
Parameters["FogVector"].SetValue(value);
}
#endregion
} }
} }

View File

@ -1,10 +1,8 @@
#region Using Statements
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.NonXNA.Development;
#endregion // Using Statements
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -12,11 +10,14 @@ using ANX.Framework.NonXNA;
namespace ANX.Framework.Graphics namespace ANX.Framework.Graphics
{ {
[PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.Untested)]
[Developer("Glatzemann, AstrorEnales")]
public class SpriteBatch : GraphicsResource public class SpriteBatch : GraphicsResource
{ {
#region Private Members private const int InitialBatchSize = 1024;
private const int InitialBatchSize = 1024;
#region Private
private Effect spriteBatchEffect; private Effect spriteBatchEffect;
private bool hasBegun; private bool hasBegun;
private SpriteSortMode currentSortMode; private SpriteSortMode currentSortMode;
@ -43,8 +44,7 @@ namespace ANX.Framework.Graphics
private static TextureComparer textureComparer = new TextureComparer(); private static TextureComparer textureComparer = new TextureComparer();
private static FrontToBackComparer frontToBackComparer = new FrontToBackComparer(); private static FrontToBackComparer frontToBackComparer = new FrontToBackComparer();
private static BackToFrontComparer backToFrontComparer = new BackToFrontComparer(); private static BackToFrontComparer backToFrontComparer = new BackToFrontComparer();
#endregion
#endregion // Private Members
#region Constructor #region Constructor
public SpriteBatch(GraphicsDevice graphicsDevice) public SpriteBatch(GraphicsDevice graphicsDevice)
@ -55,43 +55,55 @@ namespace ANX.Framework.Graphics
base.GraphicsDevice = graphicsDevice; base.GraphicsDevice = graphicsDevice;
var renderSystemCreator = AddInSystemFactory.Instance.GetDefaultCreator<IRenderSystemCreator>(); var renderSystemCreator = AddInSystemFactory.Instance.GetDefaultCreator<IRenderSystemCreator>();
this.spriteBatchEffect = new Effect(graphicsDevice, renderSystemCreator.GetShaderByteCode(NonXNA.PreDefinedShader.SpriteBatch), renderSystemCreator.GetStockShaderSourceLanguage); this.spriteBatchEffect = new Effect(graphicsDevice,
renderSystemCreator.GetShaderByteCode(NonXNA.PreDefinedShader.SpriteBatch),
renderSystemCreator.GetStockShaderSourceLanguage);
this.spriteInfos = new SpriteInfo[InitialBatchSize]; this.spriteInfos = new SpriteInfo[InitialBatchSize];
this.InitializeIndexBuffer(InitialBatchSize); this.InitializeIndexBuffer(InitialBatchSize);
this.InitializeVertexBuffer(); this.InitializeVertexBuffer();
} }
#endregion #endregion
#region Begin-Method #region Begin
public void Begin() public void Begin()
{ {
Begin(SpriteSortMode.Texture, null, null, null, null, null, Matrix.Identity); Begin(SpriteSortMode.Texture, null, null, null, null, null);
} }
public void Begin(SpriteSortMode sortMode, BlendState blendState) public void Begin(SpriteSortMode sortMode, BlendState blendState)
{ {
Begin(sortMode, blendState, null, null, null, null, Matrix.Identity); Begin(sortMode, blendState, null, null, null, null);
} }
public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState) public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState,
DepthStencilState depthStencilState, RasterizerState rasterizerState)
{ {
Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, null, Matrix.Identity); Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, null);
} }
public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect) public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState,
{ DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect)
Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, Matrix.Identity); {
if (hasBegun == true)
throw new Exception("End() has to be called before a new SpriteBatch can be started with Begin()");
hasBegun = true;
this.currentSortMode = sortMode;
this.blendState = blendState;
this.samplerState = samplerState;
this.depthStencilState = depthStencilState;
this.rasterizerState = rasterizerState;
this.effect = effect;
this.transformMatrix = Matrix.Identity;
} }
public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix transformMatrix) public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState,
DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix transformMatrix)
{ {
if (this.hasBegun == true) if (hasBegun == true)
{
throw new Exception("End() has to be called before a new SpriteBatch can be started with Begin()"); throw new Exception("End() has to be called before a new SpriteBatch can be started with Begin()");
}
hasBegun = true; hasBegun = true;
@ -104,150 +116,186 @@ namespace ANX.Framework.Graphics
this.effect = effect; this.effect = effect;
this.transformMatrix = transformMatrix; this.transformMatrix = transformMatrix;
} }
#endregion
#endregion // Begin-Method #region Draw
public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color)
{
Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width,
destinationRectangle.Height), null, color, Vector2.Zero, 0f, 0f, Vector2.One, SpriteEffects.None);
}
#region Draw-Method public void Draw(Texture2D texture, Rectangle destinationRectangle, Nullable<Rectangle> sourceRectangle, Color color)
public void Draw (Texture2D texture, Rectangle destinationRectangle, Color color) {
Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width,
destinationRectangle.Height), sourceRectangle, color, Vector2.Zero, 0f, 0f, Vector2.One, SpriteEffects.None);
}
public void Draw(Texture2D texture, Rectangle destinationRectangle, Nullable<Rectangle> sourceRectangle, Color color,
Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth)
{ {
Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width, destinationRectangle.Height), null, color, Vector2.Zero, 0.0f, 0.0f, Vector2.One, SpriteEffects.None); Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width,
} destinationRectangle.Height), sourceRectangle, color, origin, layerDepth, rotation, Vector2.One, effects);
public void Draw (Texture2D texture, Rectangle destinationRectangle, Nullable<Rectangle> sourceRectangle, Color color)
{
Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width, destinationRectangle.Height), sourceRectangle, color, Vector2.Zero, 0.0f, 0.0f, Vector2.One, SpriteEffects.None);
}
public void Draw(Texture2D texture, Rectangle destinationRectangle, Nullable<Rectangle> sourceRectangle, Color color, Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth)
{
Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width, destinationRectangle.Height), sourceRectangle, color, origin, layerDepth, rotation, Vector2.One, effects);
} }
public void Draw(Texture2D texture, Vector2 position, Color color) public void Draw(Texture2D texture, Vector2 position, Color color)
{ {
Draw(texture, position, new Vector2(texture.Width, texture.Height), null, color, Vector2.Zero, 0.0f, 0.0f, Vector2.One, SpriteEffects.None); Draw(texture, position, new Vector2(texture.Width, texture.Height), null, color, Vector2.Zero, 0f, 0f, Vector2.One,
SpriteEffects.None);
} }
public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color) public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color)
{ {
Vector2 size = sourceRectangle.HasValue ? new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) : new Vector2(texture.Width, texture.Height); Vector2 size = sourceRectangle.HasValue ?
Draw(texture, position, size, sourceRectangle, color, Vector2.Zero, 0.0f, 0.0f, Vector2.One, SpriteEffects.None); new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) :
new Vector2(texture.Width, texture.Height);
Draw(texture, position, size, sourceRectangle, color, Vector2.Zero, 0f, 0f, Vector2.One, SpriteEffects.None);
} }
public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color, Single rotation, Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth) public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color, Single rotation,
Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth)
{ {
Vector2 size = sourceRectangle.HasValue ? new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) : new Vector2(texture.Width, texture.Height); Vector2 size = sourceRectangle.HasValue ?
new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) :
new Vector2(texture.Width, texture.Height);
Draw(texture, position, size, sourceRectangle, color, origin, layerDepth, rotation, new Vector2(scale), effects); Draw(texture, position, size, sourceRectangle, color, origin, layerDepth, rotation, new Vector2(scale), effects);
} }
public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color, Single rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth) public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color, Single rotation,
{ Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth)
Vector2 size = sourceRectangle.HasValue ? new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) : new Vector2(texture.Width, texture.Height); {
Draw(texture, position, size, sourceRectangle, color, origin, layerDepth, rotation, scale, effects); Vector2 size = sourceRectangle.HasValue ?
new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) :
new Vector2(texture.Width, texture.Height);
Draw(texture, position, size, sourceRectangle, color, origin, layerDepth, rotation, scale, effects);
}
#endregion
#region DrawOptimizedText
internal void DrawOptimizedText(Texture2D texture, Vector2 position, ref Rectangle sourceRectangle, ref Color color,
float rotation, Vector2 scale, SpriteEffects effects, float layerDepth)
{
Vector2 size = new Vector2(sourceRectangle.Width, sourceRectangle.Height);
Draw(texture, position, size, sourceRectangle, color, Vector2.Zero, layerDepth, rotation, scale, effects);
}
internal void DrawOptimizedText(Texture2D texture, Vector2 position, ref Rectangle sourceRectangle, ref Color color)
{
if (hasBegun == false)
throw new InvalidOperationException("Begin() must be called before Draw()");
if (texture == null)
throw new ArgumentNullException("texture");
ResizeIfNeeded();
Vector2 bottomRight;
bottomRight.X = position.X + sourceRectangle.Width;
bottomRight.Y = position.Y + sourceRectangle.Height;
SpriteInfo currentSprite = spriteInfos[currentBatchPosition];
currentSprite.Corners = new Vector2[]
{
position,
new Vector2(bottomRight.X, position.Y),
bottomRight,
new Vector2(position.X, bottomRight.Y)
};
currentSprite.Tint = color;
currentSprite.texture = texture;
currentSprite.topLeftUV.X = sourceRectangle.X * texture.OneOverWidth;
currentSprite.topLeftUV.Y = sourceRectangle.Y * texture.OneOverHeight;
currentSprite.bottomRightUV.X = (sourceRectangle.X + sourceRectangle.Width) * texture.OneOverWidth;
currentSprite.bottomRightUV.Y = (sourceRectangle.Y + sourceRectangle.Height) * texture.OneOverHeight;
currentSprite.origin = Vector2.Zero;
currentSprite.rotation = 0f;
currentSprite.layerDepth = 1f;
spriteInfos[currentBatchPosition] = currentSprite;
currentBatchPosition++;
if (this.currentSortMode == SpriteSortMode.Immediate)
{
BatchRender(0, 1);
Flush();
}
}
#endregion
#region DrawString
public void DrawString(SpriteFont font, String text, Vector2 position, Color color)
{
if (font == null)
throw new ArgumentNullException("font");
if (text == null)
throw new ArgumentNullException("text");
font.DrawString(text, this, position, color);
} }
#endregion // Draw-Method public void DrawString(SpriteFont font, StringBuilder text, Vector2 position, Color color)
{
if (font == null)
throw new ArgumentNullException("font");
if (text == null)
throw new ArgumentNullException("text");
#region DrawString-Method font.DrawString(text.ToString(), this, position, color);
public void DrawString(SpriteFont font, String text, Vector2 position, Color color) }
{
if (font == null)
{
throw new ArgumentNullException("font");
}
if (text == null) public void DrawString(SpriteFont font, String text, Vector2 position, Color color, Single rotation, Vector2 origin,
{ Single scale, SpriteEffects effects, Single layerDepth)
throw new ArgumentNullException("text"); {
} if (font == null)
throw new ArgumentNullException("font");
if (text == null)
throw new ArgumentNullException("text");
font.DrawString(ref text, this, position, color, Vector2.One, Vector2.Zero, 0.0f, 1.0f, SpriteEffects.None); font.DrawString(text, this, position, color, new Vector2(scale), origin, rotation, layerDepth, effects);
} }
public void DrawString(SpriteFont font, String text, Vector2 position, Color color, Single rotation, Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth) public void DrawString(SpriteFont font, String text, Vector2 position, Color color, Single rotation, Vector2 origin,
{ Vector2 scale, SpriteEffects effects, Single layerDepth)
if (font == null) {
{ if (font == null)
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
} if (text == null)
throw new ArgumentNullException("text");
if (text == null) font.DrawString(text, this, position, color, scale, origin, rotation, layerDepth, effects);
{
throw new ArgumentNullException("text");
}
font.DrawString(ref text, this, position, color, new Vector2(scale), origin, rotation, layerDepth, effects);
} }
public void DrawString(SpriteFont font, String text, Vector2 position, Color color, Single rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth) public void DrawString(SpriteFont font, StringBuilder text, Vector2 position, Color color, Single rotation,
{ Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth)
if (font == null) {
{ if (font == null)
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
} if (text == null)
throw new ArgumentNullException("text");
if (text == null) font.DrawString(text.ToString(), this, position, color, new Vector2(scale), origin, rotation, layerDepth, effects);
{ }
throw new ArgumentNullException("text");
}
font.DrawString(ref text, this, position, color, scale, origin, rotation, layerDepth, effects); public void DrawString(SpriteFont font, StringBuilder text, Vector2 position, Color color, Single rotation,
} Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth)
{
if (font == null)
throw new ArgumentNullException("font");
if (text == null)
throw new ArgumentNullException("text");
public void DrawString (SpriteFont font, StringBuilder text, Vector2 position, Color color) font.DrawString(text.ToString(), this, position, color, scale, origin, rotation, layerDepth, effects);
{ }
if (font == null) #endregion
{
throw new ArgumentNullException("font");
}
if (text == null)
{
throw new ArgumentNullException("text");
}
DrawString(font, text.ToString(), position, color);
}
public void DrawString (SpriteFont font, StringBuilder text, Vector2 position, Color color, Single rotation, Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth)
{
if (font == null)
{
throw new ArgumentNullException("font");
}
if (text == null)
{
throw new ArgumentNullException("text");
}
DrawString(font, text.ToString(), position, color, rotation, origin, scale, effects, layerDepth);
}
public void DrawString (SpriteFont font, StringBuilder text, Vector2 position, Color color, Single rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth)
{
if (font == null)
{
throw new ArgumentNullException("font");
}
if (text == null)
{
throw new ArgumentNullException("text");
}
DrawString(font, text.ToString(), position, color, rotation, origin, scale, effects, layerDepth);
}
#endregion // DrawString-Method
#region End #region End
public void End() public void End()
{ {
if (hasBegun == false) if (hasBegun == false)
{
throw new Exception("Begin() has to be called before End()"); throw new Exception("Begin() has to be called before End()");
}
hasBegun = false; hasBegun = false;
@ -256,17 +304,11 @@ namespace ANX.Framework.Graphics
if (currentBatchPosition > 0) if (currentBatchPosition > 0)
{ {
if (this.currentSortMode == SpriteSortMode.Texture) if (this.currentSortMode == SpriteSortMode.Texture)
{
Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, textureComparer); Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, textureComparer);
}
else if (this.currentSortMode == SpriteSortMode.BackToFront) else if (this.currentSortMode == SpriteSortMode.BackToFront)
{
Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, backToFrontComparer); Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, backToFrontComparer);
}
else if (this.currentSortMode == SpriteSortMode.FrontToBack) else if (this.currentSortMode == SpriteSortMode.FrontToBack)
{
Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, frontToBackComparer); Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, frontToBackComparer);
}
int startOffset = 0; int startOffset = 0;
Texture2D lastTexture = spriteInfos[0].texture; Texture2D lastTexture = spriteInfos[0].texture;
@ -285,57 +327,72 @@ namespace ANX.Framework.Graphics
Flush(); Flush();
} }
#endregion #endregion
private void Draw(Texture2D texture, Vector2 topLeft, Vector2 destinationSize, Rectangle? sourceRectangle, Color tint, Vector2 origin, float layerDepth, float rotation, Vector2 scale, SpriteEffects effects) #region ResizeIfNeeded
private void ResizeIfNeeded()
{
if (currentBatchPosition >= spriteInfos.Length)
{
int newSize = spriteInfos.Length * 2;
Array.Resize<SpriteInfo>(ref spriteInfos, newSize);
InitializeIndexBuffer(newSize);
}
}
#endregion
#region Draw
private void Draw(Texture2D texture, Vector2 topLeft, Vector2 destinationSize, Rectangle? sourceRectangle,
Color tint, Vector2 origin, float layerDepth, float rotation, Vector2 scale, SpriteEffects effects)
{ {
if (hasBegun == false) if (hasBegun == false)
{
throw new InvalidOperationException("Begin() must be called before Draw()"); throw new InvalidOperationException("Begin() must be called before Draw()");
}
if (texture == null) if (texture == null)
{
throw new ArgumentNullException("texture"); throw new ArgumentNullException("texture");
}
if (currentBatchPosition >= spriteInfos.Length) ResizeIfNeeded();
{
int newSize = spriteInfos.Length * 2;
Array.Resize<SpriteInfo>(ref spriteInfos, newSize);
InitializeIndexBuffer(newSize);
}
Vector2 bottomRight = topLeft + (destinationSize * scale); Vector2 bottomRight = new Vector2(topLeft.X + (destinationSize.X * scale.X),
topLeft.Y + (destinationSize.Y * scale.Y));
spriteInfos[currentBatchPosition].Corners = new Vector2[] { topLeft, new Vector2(bottomRight.X, topLeft.Y), bottomRight, new Vector2(topLeft.X, bottomRight.Y) }; SpriteInfo currentSprite = spriteInfos[currentBatchPosition];
currentSprite.Corners = new Vector2[]
{
topLeft,
new Vector2(bottomRight.X, topLeft.Y),
bottomRight,
new Vector2(topLeft.X, bottomRight.Y)
};
spriteInfos[currentBatchPosition].Tint = tint; currentSprite.Tint = tint;
spriteInfos[currentBatchPosition].texture = texture; currentSprite.texture = texture;
if (sourceRectangle.HasValue) if (sourceRectangle.HasValue)
{ {
spriteInfos[currentBatchPosition].topLeftUV = new Vector2(sourceRectangle.Value.X / (float)texture.Width, sourceRectangle.Value.Y / (float)texture.Height); currentSprite.topLeftUV.X = sourceRectangle.Value.X * texture.OneOverWidth;
spriteInfos[currentBatchPosition].bottomRightUV = new Vector2((sourceRectangle.Value.X + sourceRectangle.Value.Width) / (float)texture.Width, (sourceRectangle.Value.Y + sourceRectangle.Value.Height) / (float)texture.Height); currentSprite.topLeftUV.Y = sourceRectangle.Value.Y * texture.OneOverHeight;
currentSprite.bottomRightUV.X = (sourceRectangle.Value.X + sourceRectangle.Value.Width) * texture.OneOverWidth;
currentSprite.bottomRightUV.Y = (sourceRectangle.Value.Y + sourceRectangle.Value.Height) * texture.OneOverHeight;
} }
else else
{ {
spriteInfos[currentBatchPosition].topLeftUV = Vector2.Zero; currentSprite.topLeftUV = Vector2.Zero;
spriteInfos[currentBatchPosition].bottomRightUV = Vector2.One; currentSprite.bottomRightUV = Vector2.One;
} }
if ((effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) if ((effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally)
{ {
float tempY = spriteInfos[currentBatchPosition].bottomRightUV.Y; float tempY = currentSprite.bottomRightUV.Y;
spriteInfos[currentBatchPosition].bottomRightUV.Y = spriteInfos[currentBatchPosition].topLeftUV.Y; currentSprite.bottomRightUV.Y = currentSprite.topLeftUV.Y;
spriteInfos[currentBatchPosition].topLeftUV.Y = tempY; currentSprite.topLeftUV.Y = tempY;
} }
if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically)
{ {
float tempX = spriteInfos[currentBatchPosition].bottomRightUV.X; float tempX = currentSprite.bottomRightUV.X;
spriteInfos[currentBatchPosition].bottomRightUV.X = spriteInfos[currentBatchPosition].topLeftUV.X; currentSprite.bottomRightUV.X = currentSprite.topLeftUV.X;
spriteInfos[currentBatchPosition].topLeftUV.X = tempX; currentSprite.topLeftUV.X = tempX;
} }
if (rotation != 0f) if (rotation != 0f)
@ -348,17 +405,22 @@ namespace ANX.Framework.Graphics
Vector2 transformVector; Vector2 transformVector;
Vector2 result; Vector2 result;
float offsetX = topLeft.X + origin.X;
float offsetY = topLeft.Y + origin.Y;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
transformVector = spriteInfos[currentBatchPosition].Corners[i] - topLeft - origin; transformVector.X = currentSprite.Corners[i].X - offsetX;
transformVector.Y = currentSprite.Corners[i].Y - offsetY;
Vector2.Transform(ref transformVector, ref this.cachedRotationMatrix, out result); Vector2.Transform(ref transformVector, ref this.cachedRotationMatrix, out result);
spriteInfos[currentBatchPosition].Corners[i] = result + topLeft + origin; currentSprite.Corners[i].X = result.X + offsetX;
currentSprite.Corners[i].Y = result.Y + offsetY;
} }
} }
spriteInfos[currentBatchPosition].origin = origin; currentSprite.origin = origin;
spriteInfos[currentBatchPosition].rotation = rotation; currentSprite.rotation = rotation;
spriteInfos[currentBatchPosition].layerDepth = layerDepth; currentSprite.layerDepth = layerDepth;
spriteInfos[currentBatchPosition] = currentSprite;
currentBatchPosition++; currentBatchPosition++;
@ -367,20 +429,18 @@ namespace ANX.Framework.Graphics
BatchRender(0, 1); BatchRender(0, 1);
Flush(); Flush();
} }
} }
#endregion
private void BatchRender(int offset, int count) #region BatchRender
private void BatchRender(int offset, int count)
{ {
int vertexCount = count * 4; int vertexCount = count * 4;
if (this.vertices == null) if (this.vertices == null)
{
this.vertices = new VertexPositionColorTexture[vertexCount]; this.vertices = new VertexPositionColorTexture[vertexCount];
}
else if (this.vertices.Length < vertexCount) else if (this.vertices.Length < vertexCount)
{
Array.Resize<VertexPositionColorTexture>(ref this.vertices, vertexCount); Array.Resize<VertexPositionColorTexture>(ref this.vertices, vertexCount);
}
int vertexPos = 0; int vertexPos = 0;
for (int i = offset; i < offset + count; i++) for (int i = offset; i < offset + count; i++)
@ -415,27 +475,34 @@ namespace ANX.Framework.Graphics
spriteBatchEffect.Parameters["Texture"].SetValue(this.spriteInfos[offset].texture); spriteBatchEffect.Parameters["Texture"].SetValue(this.spriteInfos[offset].texture);
GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexCount, 0, count * 2); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexCount, 0, count * 2);
} }
#endregion
private void Flush() #region Flush
private void Flush()
{ {
currentBatchPosition = 0; currentBatchPosition = 0;
} }
#endregion
private void InitializeIndexBuffer(int size) #region InitializeIndexBuffer
private void InitializeIndexBuffer(int size)
{ {
int indexCount = size * 6; int indexCount = size * 6;
if (this.indexBuffer == null) if (this.indexBuffer == null)
{ {
this.indexBuffer = new DynamicIndexBuffer(this.GraphicsDevice, IndexElementSize.SixteenBits, indexCount, BufferUsage.WriteOnly); this.indexBuffer = new DynamicIndexBuffer(this.GraphicsDevice, IndexElementSize.SixteenBits, indexCount,
BufferUsage.WriteOnly);
this.indexBuffer.ContentLost += new EventHandler<EventArgs>(indexBuffer_ContentLost); this.indexBuffer.ContentLost += new EventHandler<EventArgs>(indexBuffer_ContentLost);
} }
SetIndexData(indexCount); SetIndexData(indexCount);
} }
#endregion
private void indexBuffer_ContentLost(object sender, EventArgs e) #region indexBuffer_ContentLost
private void indexBuffer_ContentLost(object sender, EventArgs e)
{ {
if (this.indexBuffer != null) if (this.indexBuffer != null)
{ {
@ -445,11 +512,13 @@ namespace ANX.Framework.Graphics
} }
InitializeIndexBuffer(InitialBatchSize); InitializeIndexBuffer(InitialBatchSize);
} }
#endregion
private void SetIndexData(int indexCount) #region SetIndexData
private void SetIndexData(int indexCount)
{ {
short[] indices = new short[indexCount]; var indices = new ushort[indexCount];
int baseIndex; int baseIndex;
int baseArrayIndex; int baseArrayIndex;
@ -458,27 +527,32 @@ namespace ANX.Framework.Graphics
baseIndex = i * 4; baseIndex = i * 4;
baseArrayIndex = baseIndex + i + i; baseArrayIndex = baseIndex + i + i;
indices[baseArrayIndex] = (short)baseIndex; indices[baseArrayIndex] = (ushort)baseIndex;
indices[baseArrayIndex + 1] = (short)(baseIndex + 1); indices[baseArrayIndex + 1] = (ushort)(baseIndex + 1);
indices[baseArrayIndex + 2] = (short)(baseIndex + 2); indices[baseArrayIndex + 2] = (ushort)(baseIndex + 2);
indices[baseArrayIndex + 3] = (short)baseIndex; indices[baseArrayIndex + 3] = (ushort)baseIndex;
indices[baseArrayIndex + 4] = (short)(baseIndex + 2); indices[baseArrayIndex + 4] = (ushort)(baseIndex + 2);
indices[baseArrayIndex + 5] = (short)(baseIndex + 3); indices[baseArrayIndex + 5] = (ushort)(baseIndex + 3);
} }
this.indexBuffer.SetData<short>(indices); this.indexBuffer.SetData<ushort>(indices);
} }
#endregion
private void InitializeVertexBuffer() #region InitializeVertexBuffer
private void InitializeVertexBuffer()
{ {
if (this.vertexBuffer == null) if (this.vertexBuffer == null)
{ {
this.vertexBuffer = new DynamicVertexBuffer(this.GraphicsDevice, typeof(VertexPositionColorTexture), InitialBatchSize * 4, BufferUsage.WriteOnly); this.vertexBuffer = new DynamicVertexBuffer(this.GraphicsDevice, typeof(VertexPositionColorTexture),
this.vertexBuffer.ContentLost += new EventHandler<EventArgs>(vertexBuffer_ContentLost); InitialBatchSize * 4, BufferUsage.WriteOnly);
this.vertexBuffer.ContentLost += vertexBuffer_ContentLost;
} }
} }
#endregion
private void vertexBuffer_ContentLost(object sender, EventArgs e) #region vertexBuffer_ContentLost
private void vertexBuffer_ContentLost(object sender, EventArgs e)
{ {
this.currentBatchPosition = 0; this.currentBatchPosition = 0;
@ -490,16 +564,19 @@ namespace ANX.Framework.Graphics
} }
InitializeVertexBuffer(); InitializeVertexBuffer();
} }
#endregion
private void SetRenderStates() #region SetRenderStates
private void SetRenderStates()
{ {
GraphicsDevice.BlendState = this.blendState != null ? this.blendState : BlendState.AlphaBlend; GraphicsDevice.BlendState = blendState != null ? blendState : BlendState.AlphaBlend;
GraphicsDevice.DepthStencilState = this.depthStencilState != null ? this.depthStencilState : DepthStencilState.None; GraphicsDevice.DepthStencilState = depthStencilState != null ? depthStencilState : DepthStencilState.None;
GraphicsDevice.RasterizerState = this.rasterizerState != null ? this.rasterizerState : RasterizerState.CullCounterClockwise; GraphicsDevice.RasterizerState = rasterizerState != null ? rasterizerState : RasterizerState.CullCounterClockwise;
GraphicsDevice.SamplerStates[0] = this.samplerState != null ? this.samplerState : SamplerState.LinearClamp; GraphicsDevice.SamplerStates[0] = samplerState != null ? samplerState : SamplerState.LinearClamp;
if (cachedTransformMatrix == null || GraphicsDevice.Viewport.Width != viewportWidth || GraphicsDevice.Viewport.Height != viewportHeight) if (cachedTransformMatrix == null || GraphicsDevice.Viewport.Width != viewportWidth ||
GraphicsDevice.Viewport.Height != viewportHeight)
{ {
this.viewportWidth = GraphicsDevice.Viewport.Width; this.viewportWidth = GraphicsDevice.Viewport.Width;
this.viewportHeight = GraphicsDevice.Viewport.Height; this.viewportHeight = GraphicsDevice.Viewport.Height;
@ -518,14 +595,18 @@ namespace ANX.Framework.Graphics
cachedTransformMatrix.M42 -= cachedTransformMatrix.M22; cachedTransformMatrix.M42 -= cachedTransformMatrix.M22;
} }
this.spriteBatchEffect.Parameters["MatrixTransform"].SetValue(this.transformMatrix * cachedTransformMatrix); Matrix result;
Matrix.Multiply(ref transformMatrix, ref cachedTransformMatrix, out result);
this.spriteBatchEffect.Parameters["MatrixTransform"].SetValue(result);
spriteBatchEffect.NativeEffect.Apply(GraphicsDevice); spriteBatchEffect.NativeEffect.Apply(GraphicsDevice);
GraphicsDevice.Indices = this.indexBuffer; GraphicsDevice.Indices = this.indexBuffer;
GraphicsDevice.SetVertexBuffer(this.vertexBuffer); GraphicsDevice.SetVertexBuffer(this.vertexBuffer);
} }
#endregion
public override void Dispose() #region Dispose
public override void Dispose()
{ {
if (this.spriteBatchEffect != null) if (this.spriteBatchEffect != null)
{ {
@ -550,19 +631,18 @@ namespace ANX.Framework.Graphics
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion
private class TextureComparer : IComparer<SpriteInfo> private class TextureComparer : IComparer<SpriteInfo>
{ {
public int Compare(SpriteInfo x, SpriteInfo y) public int Compare(SpriteInfo x, SpriteInfo y)
{ {
if (x.texture.GetHashCode() > y.texture.GetHashCode()) int hash1 = x.texture.GetHashCode();
{ int hash2 = y.texture.GetHashCode();
if (hash1 > hash2)
return -1; return -1;
} else if (hash1 < hash2)
else if (x.texture.GetHashCode() < y.texture.GetHashCode())
{
return 1; return 1;
}
return 0; return 0;
} }
@ -573,13 +653,9 @@ namespace ANX.Framework.Graphics
public int Compare(SpriteInfo x, SpriteInfo y) public int Compare(SpriteInfo x, SpriteInfo y)
{ {
if (x.layerDepth > y.layerDepth) if (x.layerDepth > y.layerDepth)
{
return 1; return 1;
}
else if (x.layerDepth < y.layerDepth) else if (x.layerDepth < y.layerDepth)
{
return -1; return -1;
}
return 0; return 0;
} }
@ -590,17 +666,12 @@ namespace ANX.Framework.Graphics
public int Compare(SpriteInfo x, SpriteInfo y) public int Compare(SpriteInfo x, SpriteInfo y)
{ {
if (x.layerDepth > y.layerDepth) if (x.layerDepth > y.layerDepth)
{
return -1; return -1;
}
else if (x.layerDepth < y.layerDepth) else if (x.layerDepth < y.layerDepth)
{
return 1; return 1;
}
return 0; return 0;
} }
} }
} }
} }

View File

@ -1,9 +1,8 @@
#region Using Statements
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Text; using System.Text;
#endregion // Using Statements using ANX.Framework.NonXNA.Development;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -11,252 +10,262 @@ using System.Text;
namespace ANX.Framework.Graphics namespace ANX.Framework.Graphics
{ {
[PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.Untested)]
[Developer("Glatzemann, AstrorEnales")]
public sealed class SpriteFont public sealed class SpriteFont
{ {
#region Private Members #region Private
private Texture2D texture; private Texture2D texture;
private List<Rectangle> glyphs; private Rectangle[] glyphs;
private List<Rectangle> cropping; private Rectangle[] cropping;
private List<char> characterMap; private List<char> characterMap;
private int lineSpacing; private Vector3[] kernings;
private float horizontalSpacing; private char? defaultCharacter;
private List<Vector3> kerning; Vector2 topLeft;
private char? defaultCharacter; Vector2 position;
private ReadOnlyCollection<Char> characters; #endregion
#endregion // Private Members #region Public
public ReadOnlyCollection<Char> Characters { get; private set; }
public ReadOnlyCollection<Char> Characters public int LineSpacing { get; set; }
{ public float Spacing { get; set; }
get { return characters; }
}
public char? DefaultCharacter public char? DefaultCharacter
{ {
get { return defaultCharacter; } get { return defaultCharacter; }
set set
{ {
if (value.HasValue && !this.characterMap.Contains(value.Value)) if (value.HasValue && this.characterMap.Contains(value.Value) == false)
{
throw new NotSupportedException("Character is not in used font"); throw new NotSupportedException("Character is not in used font");
}
this.defaultCharacter = value; this.defaultCharacter = value;
} }
} }
#endregion
public int LineSpacing #region Constructor
{ internal SpriteFont(Texture2D texture, List<Rectangle> glyphs, List<Rectangle> cropping, List<char> charMap,
get { return lineSpacing; } int lineSpacing, float horizontalSpacing, List<Vector3> kerning, char? defaultCharacter)
set { lineSpacing = value; }
}
public float Spacing
{
get { return horizontalSpacing; }
set { horizontalSpacing = value; }
}
internal SpriteFont(
Texture2D texture, List<Rectangle> glyphs, List<Rectangle> cropping, List<char> charMap,
int lineSpacing, float horizontalSpacing, List<Vector3> kerning, char? defaultCharacter)
{ {
this.texture = texture; this.texture = texture;
this.glyphs = glyphs; this.glyphs = glyphs.ToArray();
this.cropping = cropping; this.cropping = cropping.ToArray();
this.characterMap = charMap; this.characterMap = charMap;
this.lineSpacing = lineSpacing; this.LineSpacing = lineSpacing;
this.horizontalSpacing = horizontalSpacing; this.Spacing = horizontalSpacing;
this.kerning = kerning; this.kernings = kerning.ToArray();
this.defaultCharacter = defaultCharacter; this.defaultCharacter = defaultCharacter;
this.characters = new ReadOnlyCollection<char>(characterMap); Characters = new ReadOnlyCollection<char>(characterMap);
} }
#endregion
public Vector2 MeasureString(string text) #region MeasureString
public Vector2 MeasureString(string text)
{ {
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
}
return InternalMeasure(ref text); return InternalMeasure(text);
} }
public Vector2 MeasureString(StringBuilder text) public Vector2 MeasureString(StringBuilder text)
{ {
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
}
String cachedText = text.ToString(); return InternalMeasure(text.ToString());
return InternalMeasure(ref cachedText);
} }
#endregion
internal void DrawString(ref String text, SpriteBatch spriteBatch, Vector2 textPos, Color color, Vector2 scale, Vector2 origin, float rotation, float layerDepth, SpriteEffects effects) #region DrawString
internal void DrawString(string text, SpriteBatch spriteBatch, Vector2 textPos, Color color, Vector2 scale,
Vector2 origin, float rotation, float layerDepth, SpriteEffects effects)
{ {
Matrix transformation = Matrix.CreateRotationZ(rotation) * Matrix.CreateTranslation(-origin.X * scale.X, -origin.Y * scale.Y, 0f); Matrix rotationMatrix;
Matrix.CreateRotationZ(rotation, out rotationMatrix);
Matrix translationMatrix;
Matrix.CreateTranslation(-origin.X * scale.X, -origin.Y * scale.Y, 0f, out translationMatrix);
Matrix transformation;
Matrix.Multiply(ref rotationMatrix, ref translationMatrix, out transformation);
topLeft.X = topLeft.Y = 0f;
int horizontalFlipModifier = 1; int horizontalFlipModifier = 1;
float width = 0f; float width = 0f;
Vector2 topLeft = new Vector2(); bool flipVertically = (effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically;
bool firstCharacterInLine = true; bool flipHorizontally = (effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally;
if ((effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) if (flipHorizontally)
{ {
topLeft.X = width = this.InternalMeasure(ref text).X * scale.X; topLeft.X = width = InternalMeasure(text).X * scale.X;
horizontalFlipModifier = -1; horizontalFlipModifier = -1;
} }
if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) if (flipVertically)
{ topLeft.Y = (InternalMeasure(text).Y - LineSpacing) * scale.Y;
topLeft.Y = (this.InternalMeasure(ref text).Y - this.lineSpacing) * scale.Y;
}
for (int i = 0; i < text.Length; i++) bool firstCharacterInLine = true;
{ for (int i = 0; i < text.Length; i++)
char currentCharacter = text[i]; {
switch (currentCharacter) char currentCharacter = text[i];
{ if (currentCharacter == '\r')
case '\r': continue;
break;
case '\n': if (currentCharacter == '\n')
firstCharacterInLine = true; {
topLeft.X = width; firstCharacterInLine = true;
if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) topLeft.X = width;
{ float factor = LineSpacing * scale.Y;
topLeft.Y -= this.lineSpacing * scale.Y; topLeft.Y += flipVertically ? -factor : factor;
} continue;
else }
{
topLeft.Y += this.lineSpacing * scale.Y;
}
break;
default: int characterIndex = GetIndexForCharacter(currentCharacter);
{ Vector3 kerning = kernings[characterIndex];
int characterIndex = GetIndexForCharacter(currentCharacter); Rectangle croppingRect = cropping[characterIndex];
Vector3 kerning = this.kerning[characterIndex];
Rectangle glyphRect = this.glyphs[characterIndex];
Rectangle croppingRect = this.cropping[characterIndex];
if (firstCharacterInLine) if (firstCharacterInLine)
{ kerning.X = Math.Max(kerning.X, 0f);
kerning.X = Math.Max(kerning.X, 0f); else
} topLeft.X += (Spacing * scale.X) * horizontalFlipModifier;
else
{
topLeft.X += (this.Spacing * scale.X) * horizontalFlipModifier;
}
topLeft.X += (kerning.X * scale.X) * horizontalFlipModifier;
if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) topLeft.X += (kerning.X * scale.X) * horizontalFlipModifier;
{
croppingRect.Y = (this.lineSpacing - glyphRect.Height) - croppingRect.Y; if (flipVertically)
} croppingRect.Y = (LineSpacing - glyphs[characterIndex].Height) - croppingRect.Y;
if ((effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally)
{ if (flipHorizontally)
croppingRect.X -= croppingRect.Width; croppingRect.X -= croppingRect.Width;
}
Vector2 position = Vector2.Transform(topLeft + (new Vector2(croppingRect.X, croppingRect.Y) * scale), transformation); position.X = topLeft.X + (croppingRect.X * scale.X);
spriteBatch.Draw(this.texture, position + textPos, glyphRect, color, rotation, Vector2.Zero, scale, effects, layerDepth); position.Y = topLeft.Y + (croppingRect.Y * scale.Y);
firstCharacterInLine = false; Vector2 result;
topLeft.X += ((kerning.Y + kerning.Z) * scale.X) * horizontalFlipModifier; Vector2.Transform(ref position, ref transformation, out result);
break; result.X += textPos.X;
} result.Y += textPos.Y;
} spriteBatch.DrawOptimizedText(texture, result, ref glyphs[characterIndex], ref color, rotation, scale,
} effects, layerDepth);
firstCharacterInLine = false;
topLeft.X += ((kerning.Y + kerning.Z) * scale.X) * horizontalFlipModifier;
}
} }
#endregion
private Vector2 InternalMeasure(ref String text) #region DrawString
internal void DrawString(string text, SpriteBatch spriteBatch, Vector2 textPos, Color color)
{
topLeft.X = topLeft.Y = 0f;
bool firstCharacterInLine = true;
for (int i = 0; i < text.Length; i++)
{
char currentCharacter = text[i];
if (currentCharacter == '\r')
continue;
if (currentCharacter == '\n')
{
firstCharacterInLine = true;
topLeft.X = 0f;
topLeft.Y += LineSpacing;
continue;
}
int characterIndex = GetIndexForCharacter(currentCharacter);
Vector3 kerning = kernings[characterIndex];
Rectangle croppingRect = cropping[characterIndex];
if (firstCharacterInLine)
kerning.X = Math.Max(kerning.X, 0f);
else
topLeft.X += Spacing;
topLeft.X += kerning.X;
position.X = topLeft.X + croppingRect.X + textPos.X;
position.Y = topLeft.Y + croppingRect.Y + textPos.Y;
spriteBatch.DrawOptimizedText(texture, position, ref glyphs[characterIndex], ref color);
firstCharacterInLine = false;
topLeft.X += kerning.Y + kerning.Z;
}
}
#endregion
#region InternalMeasure
private Vector2 InternalMeasure(string text)
{ {
if (text.Length < 1) if (text.Length < 1)
{
return Vector2.Zero; return Vector2.Zero;
}
Vector2 size = Vector2.Zero; Vector2 size = Vector2.Zero;
size.Y = this.lineSpacing; size.Y = this.LineSpacing;
float maxWidth = 0f; float maxWidth = 0f;
int currentCharacter = 0; int currentCharacter = 0;
float z = 0f; float z = 0f;
bool firstCharacterInLine = true; bool firstCharacterInLine = true;
for (int i = 0; i < text.Length; i++) for (int i = 0; i < text.Length; i++)
{ {
char currentChar = text[i]; char currentChar = text[i];
if (currentChar == '\r')
continue;
if (currentChar == '\r') if (currentChar == '\n')
{ {
continue; size.X += Math.Max(z, 0f);
} z = 0f;
maxWidth = Math.Max(size.X, maxWidth);
size = Vector2.Zero;
size.Y = LineSpacing;
firstCharacterInLine = true;
currentCharacter++;
continue;
}
if (currentChar == '\n') int currentCharIndex = GetIndexForCharacter(currentChar);
{ Vector3 kerning = kernings[currentCharIndex];
size.X += Math.Max(z, 0f); if (firstCharacterInLine)
z = 0f; kerning.X = Math.Max(kerning.X, 0f);
maxWidth = Math.Max(size.X, maxWidth); else
size = Vector2.Zero; size.X += this.Spacing + z;
size.Y = this.lineSpacing;
firstCharacterInLine = true; size.X += kerning.X + kerning.Y;
currentCharacter++; z = kerning.Z;
} size.Y = Math.Max(size.Y, (float)cropping[currentCharIndex].Height);
else firstCharacterInLine = false;
{ }
int currentCharIndex = this.GetIndexForCharacter(currentChar);
Vector3 kerning = this.kerning[currentCharIndex]; size.Y += currentCharacter * LineSpacing;
if (firstCharacterInLine)
{
kerning.X = Math.Max(kerning.X, 0f);
}
else
{
size.X += this.Spacing + z;
}
size.X += kerning.X + kerning.Y;
z = kerning.Z;
size.Y = Math.Max(size.Y, (float)this.cropping[currentCharIndex].Height);
firstCharacterInLine = false;
}
}
size.Y += currentCharacter * this.lineSpacing;
size.X = Math.Max(Math.Max(z, 0) + size.X, maxWidth); size.X = Math.Max(Math.Max(z, 0) + size.X, maxWidth);
return size; return size;
} }
#endregion
private int GetIndexForCharacter(char character) #region GetIndexForCharacter
{ private int GetIndexForCharacter(char character)
int currentIndex = 0; {
int upperBound = this.characterMap.Count - 1; int currentIndex = 0;
char testChar; int upperBound = this.characterMap.Count - 1;
int searchPos; char testChar;
int searchPos;
while (currentIndex <= upperBound) while (currentIndex <= upperBound)
{ {
searchPos = currentIndex + ((upperBound - currentIndex) >> 1); searchPos = currentIndex + ((upperBound - currentIndex) >> 1);
testChar = this.characterMap[searchPos]; testChar = characterMap[searchPos];
if (testChar == character) if (testChar == character)
{ return searchPos;
return searchPos; else if (testChar > character)
} upperBound = searchPos - 1;
else if (testChar > character) else
{ currentIndex = searchPos + 1;
upperBound = searchPos - 1; }
}
else
{
currentIndex = searchPos + 1;
}
}
if (this.defaultCharacter.HasValue) if (defaultCharacter.HasValue)
{ return GetIndexForCharacter(defaultCharacter.Value);
return this.GetIndexForCharacter(this.defaultCharacter.Value);
}
throw new ArgumentException("character not found");
}
throw new ArgumentException("character not found");
}
#endregion
} }
} }

View File

@ -8,16 +8,13 @@ namespace ANX.Framework.Graphics
{ {
internal struct SpriteInfo internal struct SpriteInfo
{ {
//public Vector2 TopLeft;
//public Vector2 BottomRight;
public Vector2[] Corners; public Vector2[] Corners;
public Color Tint; public Color Tint;
public Texture2D texture; public Texture2D texture;
public Single rotation; public float rotation;
public Vector2 origin; public Vector2 origin;
public Single layerDepth; public float layerDepth;
public Vector2 topLeftUV; public Vector2 topLeftUV;
public Vector2 bottomRightUV; public Vector2 bottomRightUV;

View File

@ -16,6 +16,9 @@ namespace ANX.Framework.Graphics
protected internal int width; protected internal int width;
protected internal int height; protected internal int height;
internal float OneOverWidth;
internal float OneOverHeight;
private INativeTexture2D nativeTexture2D; private INativeTexture2D nativeTexture2D;
private INativeTexture2D NativeTexture2D private INativeTexture2D NativeTexture2D
{ {
@ -66,6 +69,8 @@ namespace ANX.Framework.Graphics
{ {
this.width = width; this.width = width;
this.height = height; this.height = height;
OneOverWidth = 1f / width;
OneOverHeight = 1f / height;
base.levelCount = 1; base.levelCount = 1;
base.format = SurfaceFormat.Color; base.format = SurfaceFormat.Color;
@ -79,6 +84,9 @@ namespace ANX.Framework.Graphics
{ {
this.width = width; this.width = width;
this.height = height; this.height = height;
OneOverWidth = 1f / width;
OneOverHeight = 1f / height;
// TODO: pass the mipmap parameter to the creation of the texture to let the graphics card generate mipmaps! // TODO: pass the mipmap parameter to the creation of the texture to let the graphics card generate mipmaps!
base.levelCount = 1; base.levelCount = 1;
base.format = format; base.format = format;
@ -91,6 +99,8 @@ namespace ANX.Framework.Graphics
{ {
this.width = width; this.width = width;
this.height = height; this.height = height;
OneOverWidth = 1f / width;
OneOverHeight = 1f / height;
base.levelCount = mipCount; base.levelCount = mipCount;
base.format = format; base.format = format;

View File

@ -16,9 +16,6 @@ namespace ANX.Framework.Graphics
public class VertexBuffer : GraphicsResource, IGraphicsResource public class VertexBuffer : GraphicsResource, IGraphicsResource
{ {
#region Private #region Private
private VertexDeclaration vertexDeclaration;
private int vertexCount;
private BufferUsage bufferUsage;
private INativeVertexBuffer nativeVertexBuffer; private INativeVertexBuffer nativeVertexBuffer;
#endregion #endregion
@ -29,55 +26,31 @@ namespace ANX.Framework.Graphics
{ {
get get
{ {
if (this.nativeVertexBuffer == null) if (nativeVertexBuffer == null)
{
CreateNativeBuffer(); CreateNativeBuffer();
}
return this.nativeVertexBuffer; return nativeVertexBuffer;
} }
} }
public BufferUsage BufferUsage public BufferUsage BufferUsage { get; private set; }
{ public int VertexCount { get; private set; }
get public VertexDeclaration VertexDeclaration { get; private set; }
{
return this.bufferUsage;
}
}
public int VertexCount
{
get
{
return this.vertexCount;
}
}
public VertexDeclaration VertexDeclaration
{
get
{
return this.vertexDeclaration;
}
}
#endregion #endregion
#region Constructor #region Constructor
public VertexBuffer(GraphicsDevice graphicsDevice, Type vertexType, public VertexBuffer(GraphicsDevice graphicsDevice, Type vertexType, int vertexCount, BufferUsage usage)
int vertexCount, BufferUsage usage) : this(graphicsDevice, VertexTypeHelper.GetDeclaration(vertexType), vertexCount, usage)
: this(graphicsDevice, VertexBuffer.TypeToVertexDeclaration(vertexType),
vertexCount, usage)
{ {
} }
public VertexBuffer(GraphicsDevice graphicsDevice, public VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDeclaration, int vertexCount,
VertexDeclaration vertexDeclaration, int vertexCount, BufferUsage usage) BufferUsage usage)
: base(graphicsDevice) : base(graphicsDevice)
{ {
this.vertexCount = vertexCount; VertexCount = vertexCount;
this.vertexDeclaration = vertexDeclaration; VertexDeclaration = vertexDeclaration;
this.bufferUsage = usage; BufferUsage = usage;
base.GraphicsDevice.ResourceCreated += GraphicsDevice_ResourceCreated; base.GraphicsDevice.ResourceCreated += GraphicsDevice_ResourceCreated;
base.GraphicsDevice.ResourceDestroyed += GraphicsDevice_ResourceDestroyed; base.GraphicsDevice.ResourceDestroyed += GraphicsDevice_ResourceDestroyed;
@ -120,17 +93,16 @@ namespace ANX.Framework.Graphics
#region CreateNativeBuffer #region CreateNativeBuffer
private void CreateNativeBuffer() private void CreateNativeBuffer()
{ {
this.nativeVertexBuffer = var creator = AddInSystemFactory.Instance.GetDefaultCreator<IRenderSystemCreator>();
AddInSystemFactory.Instance.GetDefaultCreator<IRenderSystemCreator>().CreateVertexBuffer(GraphicsDevice, this, vertexDeclaration, vertexCount, bufferUsage); this.nativeVertexBuffer = creator.CreateVertexBuffer(GraphicsDevice, this, VertexDeclaration, VertexCount,
BufferUsage);
} }
#endregion #endregion
#region GetData #region GetData
public void GetData<T>(int offsetInBytes, T[] data, int startIndex, public void GetData<T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) where T : struct
int elementCount, int vertexStride) where T : struct
{ {
NativeVertexBuffer.GetData(offsetInBytes, data, startIndex, NativeVertexBuffer.GetData(offsetInBytes, data, startIndex, elementCount, vertexStride);
elementCount, vertexStride);
} }
public void GetData<T>(T[] data) where T : struct public void GetData<T>(T[] data) where T : struct
@ -138,19 +110,16 @@ namespace ANX.Framework.Graphics
NativeVertexBuffer.GetData(data); NativeVertexBuffer.GetData(data);
} }
public void GetData<T>(T[] data, int startIndex, int elementCount) public void GetData<T>(T[] data, int startIndex, int elementCount) where T : struct
where T : struct
{ {
NativeVertexBuffer.GetData(data, startIndex, elementCount); NativeVertexBuffer.GetData(data, startIndex, elementCount);
} }
#endregion #endregion
#region SetData #region SetData
public void SetData<T>(int offsetInBytes, T[] data, int startIndex, public void SetData<T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) where T : struct
int elementCount, int vertexStride) where T : struct
{ {
NativeVertexBuffer.SetData(GraphicsDevice, offsetInBytes, data, NativeVertexBuffer.SetData(GraphicsDevice, offsetInBytes, data, startIndex, elementCount, vertexStride);
startIndex, elementCount, vertexStride);
} }
public void SetData<T>(T[] data) where T : struct public void SetData<T>(T[] data) where T : struct
@ -164,19 +133,6 @@ namespace ANX.Framework.Graphics
} }
#endregion #endregion
#region TypeToVertexDeclaration
private static VertexDeclaration TypeToVertexDeclaration(Type t)
{
IVertexType vt = Activator.CreateInstance(t) as IVertexType;
if (vt != null)
{
return vt.VertexDeclaration;
}
return null;
}
#endregion
#region Dispose #region Dispose
public override void Dispose() public override void Dispose()
{ {
@ -186,16 +142,17 @@ namespace ANX.Framework.Graphics
nativeVertexBuffer = null; nativeVertexBuffer = null;
} }
if (vertexDeclaration != null) // do not dispose the VertexDeclaration here, because it's only a reference
{ if (VertexDeclaration != null)
// do not dispose the VertexDeclaration here, because it's only a reference VertexDeclaration = null;
vertexDeclaration = null;
}
} }
protected override void Dispose([MarshalAs(UnmanagedType.U1)] bool disposeManaged) protected override void Dispose([MarshalAs(UnmanagedType.U1)] bool disposeManaged)
{ {
throw new NotImplementedException(); if (disposeManaged)
{
Dispose();
}
} }
#endregion #endregion
} }

View File

@ -2,6 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using ANX.Framework.Graphics; using ANX.Framework.Graphics;
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.NonXNA.RenderSystem namespace ANX.Framework.NonXNA.RenderSystem
{ {
internal static class VertexTypeHelper internal static class VertexTypeHelper
@ -14,7 +18,17 @@ namespace ANX.Framework.NonXNA.RenderSystem
if (rememberedInstances.ContainsKey(type) == false) if (rememberedInstances.ContainsKey(type) == false)
rememberedInstances.Add(type, Activator.CreateInstance<T>()); rememberedInstances.Add(type, Activator.CreateInstance<T>());
return rememberedInstances[type].VertexDeclaration; var result = rememberedInstances[type];
return result != null ? result.VertexDeclaration : null;
}
public static VertexDeclaration GetDeclaration(Type type)
{
if (rememberedInstances.ContainsKey(type) == false)
rememberedInstances.Add(type, Activator.CreateInstance(type) as IVertexType);
var result = rememberedInstances[type];
return result != null ? result.VertexDeclaration : null;
} }
} }
} }

View File

@ -21,11 +21,18 @@ namespace TextRendering
SpriteFont debugFont; SpriteFont debugFont;
int fps = 60;
int fpsCount = 0;
float fpsTimer = 0f;
public Game1() public Game1()
{ {
graphics = new GraphicsDeviceManager(this); graphics = new GraphicsDeviceManager(this);
graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings); graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
Content.RootDirectory = "SampleContent"; Content.RootDirectory = "SampleContent";
IsFixedTimeStep = false;
graphics.SynchronizeWithVerticalRetrace = false;
} }
void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e) void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
@ -55,6 +62,15 @@ namespace TextRendering
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit(); this.Exit();
fpsCount++;
fpsTimer += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (fpsTimer >= 1f)
{
fpsTimer -= 1f;
fps = fpsCount;
fpsCount = 0;
}
base.Update(gameTime); base.Update(gameTime);
} }
@ -63,7 +79,7 @@ namespace TextRendering
GraphicsDevice.Clear(Color.CornflowerBlue); GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.FrontToBack, null); spriteBatch.Begin(SpriteSortMode.FrontToBack, null);
spriteBatch.DrawString(this.debugFont, "Hello World!", new Vector2(100, 100), Color.White); spriteBatch.DrawString(this.debugFont, "Hello World! FPS: " + fps, new Vector2(100, 100), Color.White);
spriteBatch.DrawString(this.debugFont, "This screen is powered by the ANX.Framework!\r\nsecond line", new Vector2(100, 100 + this.debugFont.LineSpacing), Color.Black, 0.0f, new Vector2(1, -1), Vector2.One, SpriteEffects.None, 0.0f); spriteBatch.DrawString(this.debugFont, "This screen is powered by the ANX.Framework!\r\nsecond line", new Vector2(100, 100 + this.debugFont.LineSpacing), Color.Black, 0.0f, new Vector2(1, -1), Vector2.One, SpriteEffects.None, 0.0f);
spriteBatch.DrawString(this.debugFont, "This screen is powered by the ANX.Framework!\r\nsecond line", new Vector2(100, 100 + this.debugFont.LineSpacing), Color.Red, 0.0f, Vector2.Zero, Vector2.One, SpriteEffects.None, 1.0f); spriteBatch.DrawString(this.debugFont, "This screen is powered by the ANX.Framework!\r\nsecond line", new Vector2(100, 100 + this.debugFont.LineSpacing), Color.Red, 0.0f, Vector2.Zero, Vector2.One, SpriteEffects.None, 1.0f);

View File

@ -11,6 +11,7 @@ namespace TextRendering
static void Main(string[] args) static void Main(string[] args)
{ {
//AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "OpenGL3"); //AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "OpenGL3");
AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "DirectX10");
//AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "DirectX11"); //AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "DirectX11");
using (Game1 game = new Game1()) using (Game1 game = new Game1())