Skip to content

Commit

Permalink
Implemented DebugBar instead of Statistics.cs, which now exposes the …
Browse files Browse the repository at this point in the history
…IStatistics service and draws a pretty background.
  • Loading branch information
Hüseyin Uslu committed Jan 26, 2013
1 parent 635c682 commit 5fe98b7
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 103 deletions.
2 changes: 1 addition & 1 deletion src/Engine/Core/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private void AddComponents()
this.Game.Components.Add(new UserInterface(this.Game));

this.Game.Components.Add(new InGameDebugger(this.Game));
this.Game.Components.Add(new Statistics(this.Game));
this.Game.Components.Add(new DebugBar(this.Game));
this.Game.Components.Add(new GraphManager(this.Game));

#if XNA
Expand Down
186 changes: 106 additions & 80 deletions src/Engine/Debugging/Statistics.cs → src/Engine/Debugging/DebugBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
*/

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
Expand All @@ -16,6 +18,7 @@
using VoxeliqEngine.Common.Extensions;
using VoxeliqEngine.Common.Logging;
using VoxeliqEngine.Core;
using VoxeliqEngine.Graphics.Drawing;
using VoxeliqEngine.Universe;

namespace VoxeliqEngine.Debugging
Expand Down Expand Up @@ -43,33 +46,35 @@ public interface IStatistics
int RemovalQueue { get; }
}

public sealed class Statistics : DrawableGameComponent, IStatistics
internal class DebugBar : DrawableGameComponent, IStatistics
{
// fps stuff.
public int FPS { get; private set; } // the current FPS.
// exported statistics.
public int FPS { get; private set; }
public long MemoryUsed { get { return GC.GetTotalMemory(false); } }
public int GenerateQueue { get; private set; }
public int LightenQueue { get; private set; }
public int BuildQueue { get; private set; }
public int ReadyQueue { get; private set; }
public int RemovalQueue { get; private set; }

// internal counters.
private int _frameCounter = 0; // the frame count.
private TimeSpan _elapsedTime = TimeSpan.Zero;

// memory stuff
/// <summary>
/// Returns the memory size.
/// </summary>
/// <returns></returns>
public long MemoryUsed
{
get { return GC.GetTotalMemory(false); }
}

// drawn-text stuff.
// drawn-blocks stuff.
private string _drawnBlocks;
private string _totalBlocks;

// resources.
private PrimitiveBatch _primitiveBatch;
private SpriteBatch _spriteBatch;
private SpriteFont _spriteFont;
private Matrix _localProjection;
private Matrix _localView;
private Rectangle _bounds;
private readonly Vector2[] _backgroundPolygon = new Vector2[4];

// for grabbing internal string, we should init string builder capacity and max capacity ctor so that, grabbed internal string is always valid.
// http://www.gavpugh.com/2010/03/23/xnac-stringbuilder-to-string-with-no-garbage/
// for grabbing internal string, we should init string builder capacity and max capacity ctor so that, grabbed internal string is always valid. - http://www.gavpugh.com/2010/03/23/xnac-stringbuilder-to-string-with-no-garbage/
private readonly StringBuilder _stringBuilder = new StringBuilder(512, 512);

// required services.
Expand All @@ -80,53 +85,51 @@ public long MemoryUsed
private IChunkCache _chunkCache;
private IAssetManager _assetManager;

public int GenerateQueue { get; private set; }
public int LightenQueue { get; private set; }
public int BuildQueue { get; private set; }
public int ReadyQueue { get; private set; }
public int RemovalQueue { get; private set; }

// misc.
private static readonly Logger Logger = LogManager.CreateLogger(); // loging-facility

/// <summary>
/// Creates a new statistics service instance.
/// </summary>
/// <param name="game"></param>
public Statistics(Game game)
public DebugBar(Game game)
: base(game)
{
this.Game.Services.AddService(typeof (IStatistics), this); // export the service.
this.Game.Services.AddService(typeof(IStatistics), this); // export the service.
}

/// <summary>
/// Initializes the statistics service.
/// Initializes the debug-bar service.
/// </summary>
public override void Initialize()
{
Logger.Trace("init()");

// import required services.
this._player = (IPlayer) this.Game.Services.GetService(typeof (IPlayer));
this._fogger = (IFogger) this.Game.Services.GetService(typeof (IFogger));
this._world = (IWorld) this.Game.Services.GetService(typeof (IWorld));
this._chunkStorage = (IChunkStorage) this.Game.Services.GetService(typeof (IChunkStorage));
this._chunkCache = (IChunkCache) this.Game.Services.GetService(typeof (IChunkCache));

this._player = (IPlayer)this.Game.Services.GetService(typeof(IPlayer));
this._fogger = (IFogger)this.Game.Services.GetService(typeof(IFogger));
this._world = (IWorld)this.Game.Services.GetService(typeof(IWorld));
this._chunkStorage = (IChunkStorage)this.Game.Services.GetService(typeof(IChunkStorage));
this._chunkCache = (IChunkCache)this.Game.Services.GetService(typeof(IChunkCache));
this._assetManager = (IAssetManager)this.Game.Services.GetService(typeof(IAssetManager));

if (this._assetManager == null)
throw new NullReferenceException("Can not find asset manager component.");

base.Initialize();
}

/// <summary>
/// Loads required assets & content.
/// </summary>
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
_spriteFont = this._assetManager.Verdana;
// load resources.
this._primitiveBatch = new PrimitiveBatch(this.GraphicsDevice, 1000);
this._localProjection = Matrix.CreateOrthographicOffCenter(0f, this.GraphicsDevice.Viewport.Width, this.GraphicsDevice.Viewport.Height, 0f, 0f, 1f);
this._localView = Matrix.Identity;
this._spriteBatch = new SpriteBatch(GraphicsDevice);
this._spriteFont = this._assetManager.Verdana;

// init bounds.
this._bounds = new Rectangle(10, 10, this.Game.GraphicsDevice.Viewport.Bounds.Width - 20, 20);
this._backgroundPolygon[0] = new Vector2(_bounds.X - 2, _bounds.Y - 2); // top left
this._backgroundPolygon[1] = new Vector2(_bounds.X - 2, _bounds.Y + _bounds.Height + 14); // bottom left
this._backgroundPolygon[2] = new Vector2(_bounds.X + 2 + _bounds.Width, _bounds.Y + _bounds.Height + 14); // bottom right
this._backgroundPolygon[3] = new Vector2(_bounds.X + 2 + _bounds.Width, _bounds.Y - 2); // top right
}

/// <summary>
Expand All @@ -148,75 +151,74 @@ public override void Update(GameTime gameTime)
/// Draws the statistics.
/// </summary>
/// <param name="gameTime"></param>
public override void Draw(GameTime gameTime)
public override void Draw(GameTime gameTime)
{
// Attention: DO NOT use string.format as it's slower than string concat.

_frameCounter++;

// backup the raster and depth-stencil states.
var previousRasterizerState = this.Game.GraphicsDevice.RasterizerState;
var previousDepthStencilState = this.Game.GraphicsDevice.DepthStencilState;

// set new states for drawing primitive shapes.
this.Game.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
this.Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

_primitiveBatch.Begin(this._localProjection, this._localView); // initialize the primitive batch.

BasicShapes.DrawSolidPolygon(this._primitiveBatch, this._backgroundPolygon, 4, Color.Black, true);

_primitiveBatch.End(); // end the batch.

// restore old states.
this.Game.GraphicsDevice.RasterizerState = previousRasterizerState;
this.Game.GraphicsDevice.DepthStencilState = previousDepthStencilState;

// calculate drawn blocks
if (this._chunkCache.ChunksDrawn >= 31)
_drawnBlocks = (this._chunkCache.ChunksDrawn / 31f).ToString("F2") + "M";
else if (this._chunkCache.ChunksDrawn > 1)
_drawnBlocks = (this._chunkCache.ChunksDrawn / 0.03f).ToString("F2") + "K";
else _drawnBlocks = "0";

if (this._chunkStorage.Count > 31) _totalBlocks = (this._chunkStorage.Count / 31f).ToString("F2") + "M";
else if (this._chunkStorage.Count > 1) _totalBlocks = (this._chunkStorage.Count / 0.03f).ToString("F2") + "K";
else _totalBlocks = Engine.Instance.Configuration.Chunk.Volume.ToString(CultureInfo.InvariantCulture);
// calculate total blocks
if (this._chunkStorage.Count > 31)
_totalBlocks = (this._chunkStorage.Count / 31f).ToString("F2") + "M";
else if (this._chunkStorage.Count > 1)
_totalBlocks = (this._chunkStorage.Count / 0.03f).ToString("F2") + "K";
else
_totalBlocks = Engine.Instance.Configuration.Chunk.Volume.ToString(CultureInfo.InvariantCulture);

_spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);

// Attention: DO NOT use string.format as it's slower than string concat.

// FPS
_stringBuilder.Length = 0;
_stringBuilder.Append("fps:");
_stringBuilder.Append(this.FPS);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(5, 5), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 5, this._bounds.Y + 5), Color.White);

// mem used
_stringBuilder.Length = 0;
_stringBuilder.Append("mem:");
_stringBuilder.Append(this.MemoryUsed.GetKiloString());
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(75, 5), Color.White);

// player position
_stringBuilder.Length = 0;
_stringBuilder.Append("pos:");
_stringBuilder.Append(this._player.Position);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(190, 5), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 105, this._bounds.Y + 5), Color.White);

// chunks
_stringBuilder.Length = 0;
_stringBuilder.Append("chunks:");
_stringBuilder.AppendNumber(this._chunkCache.ChunksDrawn);
_stringBuilder.Append('/');
_stringBuilder.AppendNumber(this._chunkStorage.Count);
_spriteBatch.DrawString(_spriteFont, _stringBuilder,new Vector2(5, 20), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 205, this._bounds.Y + 5), Color.White);

// blocks
_stringBuilder.Length = 0;
_stringBuilder.Append("blocks:");
_stringBuilder.Append(_drawnBlocks);
_stringBuilder.Append('/');
_stringBuilder.Append(_totalBlocks);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(130, 20), Color.White);

// infinitive world
_stringBuilder.Length = 0;
_stringBuilder.Append("inf:");
_stringBuilder.Append(Engine.Instance.Configuration.World.IsInfinitive ? "On" : "Off");
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(5, 35), Color.White);

// fly
_stringBuilder.Length = 0;
_stringBuilder.Append("fly:");
_stringBuilder.Append(this._player.FlyingEnabled ? "On" : "Off");
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(60, 35), Color.White);

// fog
_stringBuilder.Length = 0;
_stringBuilder.Append("fog:");
_stringBuilder.Append(this._fogger.State);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(120, 35), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 305, this._bounds.Y + 5), Color.White);

// process queues.
this.GenerateQueue = this._chunkCache.StateStatistics[ChunkState.AwaitingGenerate] + this._chunkCache.StateStatistics[ChunkState.Generating];
Expand All @@ -229,33 +231,57 @@ public override void Draw(GameTime gameTime)
_stringBuilder.Length = 0;
_stringBuilder.Append("GenerateQ:");
_stringBuilder.AppendNumber(this.GenerateQueue);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(5, 65), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 450, this._bounds.Y + 5), Color.White);

// chunk lighting queue
_stringBuilder.Length = 0;
_stringBuilder.Append("LightenQ:");
_stringBuilder.AppendNumber(this.LightenQueue);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(5, 80), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 550, this._bounds.Y + 5), Color.White);

// chunk build queue
_stringBuilder.Length = 0;
_stringBuilder.Append("BuildQ:");
_stringBuilder.AppendNumber(this.BuildQueue);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(5, 95), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 650, this._bounds.Y + 5), Color.White);

// ready chunks queue
_stringBuilder.Length = 0;
_stringBuilder.Append("Ready:");
_stringBuilder.AppendNumber(this.ReadyQueue);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(5, 110), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 750, this._bounds.Y + 5), Color.White);

// chunk removal queue
_stringBuilder.Length = 0;
_stringBuilder.Append("Removal:");
_stringBuilder.AppendNumber(this.RemovalQueue);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(5, 125), Color.White);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 850, this._bounds.Y + 5), Color.White);

// infinitive world
_stringBuilder.Length = 0;
_stringBuilder.Append("inf:");
_stringBuilder.Append(Engine.Instance.Configuration.World.IsInfinitive ? "On" : "Off");
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 5, this._bounds.Y + 15), Color.White);

// fly
_stringBuilder.Length = 0;
_stringBuilder.Append("fly:");
_stringBuilder.Append(this._player.FlyingEnabled ? "On" : "Off");
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 105, this._bounds.Y + 15), Color.White);

// fog
_stringBuilder.Length = 0;
_stringBuilder.Append("fog:");
_stringBuilder.Append(this._fogger.State);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 205, this._bounds.Y + 15), Color.White);

// player position
_stringBuilder.Length = 0;
_stringBuilder.Append("pos:");
_stringBuilder.Append(this._player.Position);
_spriteBatch.DrawString(_spriteFont, _stringBuilder, new Vector2(this._bounds.X + 305, this._bounds.Y + 15), Color.White);

_spriteBatch.End();
}
}
}
}
10 changes: 5 additions & 5 deletions src/Engine/Debugging/Graphs/DebugGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class DebugGraph
/// <summary>
/// Used for drawing the background shape.
/// </summary>
protected readonly Vector2[] Background = new Vector2[4];
protected readonly Vector2[] BackgroundPolygon = new Vector2[4];

/// <summary>
/// Current maximum value.
Expand Down Expand Up @@ -133,10 +133,10 @@ protected virtual void Initialize()
public void LoadContent()
{
// calculate the coordinates for drawing the background.
Background[0] = new Vector2(Bounds.X - 2, Bounds.Y - 2); // top left
Background[3] = new Vector2(Bounds.X + 2 + Bounds.Width, Bounds.Y - 2); // top right
Background[1] = new Vector2(Bounds.X - 2, Bounds.Y + Bounds.Height + 14); // bottom left
Background[2] = new Vector2(Bounds.X + 2 + Bounds.Width, Bounds.Y + Bounds.Height + 14); // bottom right
BackgroundPolygon[0] = new Vector2(Bounds.X - 2, Bounds.Y - 2); // top left
BackgroundPolygon[3] = new Vector2(Bounds.X + 2 + Bounds.Width, Bounds.Y - 2); // top right
BackgroundPolygon[1] = new Vector2(Bounds.X - 2, Bounds.Y + Bounds.Height + 14); // bottom left
BackgroundPolygon[2] = new Vector2(Bounds.X + 2 + Bounds.Width, Bounds.Y + Bounds.Height + 14); // bottom right
}

/// <summary>
Expand Down
14 changes: 7 additions & 7 deletions src/Engine/Debugging/Graphs/GraphManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ public GraphManager(Game game)
public override void Initialize()
{
// create the graphs modules.
this._graphs.Add(new FPSGraph(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 10, 270, 35)));
this._graphs.Add(new MemGraph(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 65, 270, 35)));
this._graphs.Add(new GenerateQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 120, 270, 35)));
this._graphs.Add(new LightenQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 175, 270, 35)));
this._graphs.Add(new BuildQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 230, 270, 35)));
this._graphs.Add(new ReadyQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 285, 270, 35)));
this._graphs.Add(new RemoveQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 340, 270, 35)));
this._graphs.Add(new FPSGraph(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 50, 270, 35)));
this._graphs.Add(new MemGraph(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 105, 270, 35)));
this._graphs.Add(new GenerateQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 160, 270, 35)));
this._graphs.Add(new LightenQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 215, 270, 35)));
this._graphs.Add(new BuildQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 270, 270, 35)));
this._graphs.Add(new ReadyQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 325, 270, 35)));
this._graphs.Add(new RemoveQ(this.Game, new Rectangle(Engine.Instance.Configuration.Graphics.Width - 280, 380, 270, 35)));

// import required services.
this._assetManager = (IAssetManager)this.Game.Services.GetService(typeof(IAssetManager));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public override void DrawStrings(GameTime gameTime)

public override void DrawGraph(GameTime gameTime)
{
BasicShapes.DrawSolidPolygon(this.PrimitiveBatch, Background, 4, Color.Black, true);
BasicShapes.DrawSolidPolygon(this.PrimitiveBatch, BackgroundPolygon, 4, Color.Black, true);

float x = Bounds.X;
float deltaX = Bounds.Width / (float)ValuesToGraph;
Expand Down
Loading

0 comments on commit 5fe98b7

Please sign in to comment.