//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {License Information: Creative Commons}
//---------------------------------------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using System.ComponentModel;
using System.Xml;
using DWGame.Globals;
using DW.Stream;
namespace DW.UserInterface_2D
{
///
/// Creates, updates, and draws a heads up display on the user's viewport.
///
public class HUD
{
public Rectangle currentScreenSpaceView;
//public Rectangle localSpaceView;
//Vector2 currentDimensions = new Vector2(800, 600);
Vector2 HudScaleMultiplier;
public static Texture2D backgrnd;
// The nameID of the image that the second needs to get the location from
private string imageReference;
private Vector2 imageOffset = new Vector2();
// An addition modifier to the image location, must be 0 if null
private int modifier;
// Text Display specific
private string operation;
private string textToScreen;
private Vector2 offset;
private const int MARGIN_GUTTER = 15;
private const int SCROLL = 20;
private int dialogueBoxIndex;
private int speakerTextIndex;
private int dialogueTextIndex;
private int displayLength = 0;
public List textDisplays { get { return _textDisplays; } set { _textDisplays = value; } }
private List _textDisplays = new List();
public List imageDisplays { get { return _imageDisplays; } set { _imageDisplays = value; } }
public List _imageDisplays = new List();
public List imageSpinners { get { return _imageSpinners; } set { _imageSpinners = value; } }
private List _imageSpinners = new List();
///
/// Heads Up Display constructor.
///
public HUD(Viewport view)
{
currentScreenSpaceView.X = view.X;
currentScreenSpaceView.Y = view.Y;
currentScreenSpaceView.Width = view.Width;
currentScreenSpaceView.Height = view.Height;
}
///
/// Accessor for the objects on the HUD
///
/// Search string (XML name) of the HUD item you are looking for
///
public int getHUDIndex(string name)
{
for (int x = 0; x < imageDisplays.Count; x++)
{
if (imageDisplays[x].name == name)
{
return x;
}
else
{
for (int z = 0; z < textDisplays.Count; z++)
{
if (textDisplays[z].name == name)
{
return z;
}
}
}
}
return 0;
}
#region HUDCreation
///
/// Generate the HUD from XML file
///
public void LoadScreenObjects(XmlNode screenObjects)
{
try
{
foreach (XmlNode screenObjNode in screenObjects.ChildNodes)
{
LoadDisplays(screenObjNode);
}
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("Error reading xml");
throw e;
}
InitializeDialogControl();
}
///
/// Loads the imageDisplay into the imageDisplays list
/// Loads the textDisplay into the textDisplays list
///
/// XML Node ImageDisplay
private void LoadDisplays(XmlNode node)
{
if (node.Name == "ImageDisplay")
{
ImageDisplay so = new ImageDisplay(node);
if (node.Attributes["quadrant"].Value != "null")
{
LocationsTranslation(so, node.Attributes["quadrant"].Value);
//so.position += new Vector2(int.Parse(node.Attributes["imageOffsetX"].Value),int.Parse(node.Attributes["imageOffsetY"].Value));
}
if (node.Attributes["imageReference"].Value != "null")
{
// AdjustLocationBasedOnReferenceImage(so);
}
AddImageDisplay(so);
}
else if (node.Name == "TextDisplay")
{
TextDisplay so = new TextDisplay(node);
if (node.Attributes["quadrant"].Value != "null")
{
//LocationsTranslation(so, node.Attributes["quadrant"].Value);//new Vector2(gameFonts.Arial.MeasureString(this.textToScreen).X, textureImage.Height));
//so.position += new Vector2(int.Parse(node.Attributes["offsetX"].Value), int.Parse(node.Attributes["offsetY"].Value));
}
string imgRef = node.Attributes["imageReference"].Value;
if (imgRef != "null")
{
for (int x = 0; x < imageDisplays.Count; x++)
{
if (imageDisplays[x].name == imgRef)
{
so.position = imageDisplays[x].position + offset;
AddTextDisplay(so);
}
}
}
else { AddTextDisplay(so); }
}
backgrnd = Renderer.content.Load("Spicybgrnd");
}
///
/// Add an Image display to our ImageDisplay list.
///
/// Image to display
/// Name of the image
/// Position to display image
/// Width of the image's texture
/// Height of the image's texture
/// Color of the image
/// Toggle to turn draw on/off
public void AddImageDisplay(Texture2D image, string name, Vector2 position, int width, int height, Color color, bool draw)
{
ImageDisplay temp = new ImageDisplay();
temp.image = image;
temp.name = name;
temp.width = width;
temp.height = height;
temp.position = position;
temp.color = color;
temp.visible = draw;
AddImageDisplay(temp);
}
private void AddImageDisplay(ImageDisplay display)
{
_imageDisplays.Add(display);
}
///
/// Add a Text display to the TextDisplay list.
///
/// ID of the text to be displayed
/// Text to add
/// Position on the HUD
/// Color to display the text in
/// Toggle to turn draw on/off
///
public int AddTextDisplay(string nameID, string text, Vector2 position, Color color, bool draw)
{
TextDisplay temp = new TextDisplay();
temp.name = nameID;
temp.text = text;
Vector2 size = Renderer.SystemFonts.Arial.MeasureString(text);
temp.width = (int)(size.X);
temp.height = (int)(size.Y);
temp.position = position;
temp.color = color;
temp.visible = draw;
AddTextDisplay(temp);
return textDisplays.Count - 1;
}
private void AddTextDisplay(TextDisplay display)
{
textDisplays.Add(display);
}
#endregion
#region Loading HUD helper methods
///
/// Translate from XML quadrant to viewport location
///
/// Size of Image or Text String
private void LocationsTranslation(ImageDisplay so, string quadrant)
{
// Upper, Left
so.position = new Vector2(0, 0);
// Center, Right, Middle, Bottom
if (quadrant.Contains("C")) {
so.position.X = (this.currentScreenSpaceView.Width/2 - so.image.Width/2); }
if (quadrant.Contains("R")) {
so.position.X = this.currentScreenSpaceView.Width - so.image.Width - 0; }
if (quadrant.Contains("M")) { so.position.Y = (this.currentScreenSpaceView.Height/2 - so.image.Height/2); }
if (quadrant.Contains("B")) { so.position.Y = this.currentScreenSpaceView.Height - so.image.Height - 0; }
}
///
/// Translate from XML quadrant to viewport location
///
/// Size of Image or Text String
private void LocationsTranslation(TextDisplay so, string quadrant)
{
// Upper, Left
so.position = new Vector2(MARGIN_GUTTER, MARGIN_GUTTER);
if (so is TextDisplay)
{
so.position.X = Renderer.SystemFonts.Arial.MeasureString(so.text).X;
}
// Center, Right, Middle, Bottom
if (quadrant.Contains("C")) { so.position.X = (this.currentScreenSpaceView.Width - so.position.X) / 2; }
if (quadrant.Contains("R")) { so.position.X = this.currentScreenSpaceView.Width - so.position.X - MARGIN_GUTTER; }
if (quadrant.Contains("M")) { so.position.Y = (this.currentScreenSpaceView.Height - so.position.Y) / 2; }
if (quadrant.Contains("B")) { so.position.Y = this.currentScreenSpaceView.Height - so.position.Y - MARGIN_GUTTER; }
}
///
/// If the image has a reference variable, loads the image based on the imageAttribute.
/// Called by LoadImageDisplays
///
//private void AdjustLocationBasedOnReferenceImage(ScreenObject so)
//{
// if (imageReference == "self")
// {
// if (imageAttribute == "height")
// {
// so.position.Y = so.position.Y - (textureImage.Height + 10);
// }
// else if (imageAttribute == "width")
// {
// so.position.X = so.position.X - (textureImage.Width / 2);
// }
// else if (imageAttribute == "both")
// {
// so.position.Y = so.position.Y - (textureImage.Height / 2);
// so.position.X = so.position.X - (textureImage.Width / 2);
// }
// }
// else
// {
// for (int x = 0; x < imageDisplays.Count; x++)
// {
// if (imageDisplays[x].name == imageReference)
// {
// if (imageAttribute != null)
// {
// if (imageAttribute == "width")
// {
// so.position.X = MARGIN_GUTTER + modifier + imageDisplays[x].width;
// }
// else if (imageAttribute == "height")
// {
// so.position.Y = imageDisplays[x].height;
// }
// else if (imageAttribute == "both")
// {
// so.position.X = MARGIN_GUTTER + modifier + imageDisplays[x].width;
// so.position.Y = imageDisplays[x].height;
// }
// }
// }
// }
// }
//}
#endregion
public void Update(GameTime gameTime)
{
UpdateDialogue();
}
///
/// Removes dialogue once time limit expires
///
public void UpdateDialogue()
{
//Remove dialogue once the limit has passed
if (imageDisplays[getHUDIndex("dialogueBox")].stopWatch.ElapsedMilliseconds >= displayLength)
{
RemoveDialog();
imageDisplays[getHUDIndex("dialogueBox")].stopWatch.Reset();
displayLength = 0;
}
}
#region Dialogue Controls
///
/// Inits the dialogue control system
///
public void InitializeDialogControl()
{
imageDisplays[getHUDIndex("dialogueBox")].stopWatch.Reset();
}
///
/// Shows the dialogue
///
/// Which image to post in the background
/// Who is talking
/// What the message is
public void ShowDialog(Texture2D backgroundImage, string speaker, string message)
{
imageDisplays[getHUDIndex("dialogueBox")].visible = true;
textDisplays[getHUDIndex("speakerText")].text = speaker;
textDisplays[getHUDIndex("speakerText")].visible = true;
textDisplays[getHUDIndex("dialogueText")].text = message;
textDisplays[getHUDIndex("dialogueText")].visible = true;
}
///
/// Removes the dialogue from the HUD
///
public void RemoveDialog()
{
imageDisplays[dialogueBoxIndex].visible = false;
textDisplays[getHUDIndex("dialogueBox")].text = "ERROR";
textDisplays[getHUDIndex("speakerText")].visible = false;
textDisplays[getHUDIndex("speakerText")].color = Color.White;
textDisplays[getHUDIndex("dialogueText")].text = "YOU SHOULDN'T EVER SEE THIS";
textDisplays[getHUDIndex("dialogueText")].visible = false;
textDisplays[getHUDIndex("dialogueText")].color = Color.White;
}
///
/// Displays the dialogue on the HUD
///
/// Which image to post in the background
/// Who is talking
/// What the message is
/// Time limit to display message
public void DisplayDialog(Texture2D backgroundImage, string speaker, string message, int limitMilli)
{
displayLength = limitMilli;
if (!imageDisplays[getHUDIndex("dialogueBox")].stopWatch.IsRunning)
{
displayLength = limitMilli;
imageDisplays[getHUDIndex("dialogueBox")].stopWatch.Start();
}
else
{
displayLength = limitMilli;
imageDisplays[getHUDIndex("dialogueBox")].stopWatch.Reset();
}
ShowDialog(backgroundImage, speaker, message);
}
#endregion
#region Draw functions
///
/// Default Draw function.
///
/// SpriteBatch used to draw used to draw.
public void Draw(SpriteBatch spriteBatch)
{
Draw(spriteBatch, this.currentScreenSpaceView.X, this.currentScreenSpaceView.Y);
}
///
/// Draw function for drawing our displays at a certain offset position.
/// NOTE: SpriteBatch Begin and End are handled outside this scope.
///
/// SpriteBatch used to draw used to draw.
/// X-Offset to draw location.
/// Y-Offset to draw location.
public void Draw(SpriteBatch spriteBatch, int xoffset, int yoffset)
{
spriteBatch.Draw(backgrnd, currentScreenSpaceView, Color.White);
foreach (ImageDisplay element in _imageDisplays)
{
if (element.visible == true)
{
spriteBatch.Draw(element.image,
new Rectangle((int)element.position.X + xoffset,
(int)element.position.Y + yoffset,
(int)(element.Size.Width * HudScaleMultiplier.X),
(int)(element.Size.Height * HudScaleMultiplier.Y)),
element.Source,
element.color);
}
}
foreach (TextDisplay element in textDisplays)
{
if (element.visible)
{
spriteBatch.DrawString(Renderer.SystemFonts.Arial, element.text, element.position, element.color);
}
}
}
///
/// Resizes the HUD based on viewport change
///
/// The ratio between old viewport and resized viewport
public void Resize(Rectangle viewPortRect)
{
if (currentScreenSpaceView != viewPortRect)
{
// Determine multiplier and store new size
HudScaleMultiplier =
new Vector2(viewPortRect.Width, viewPortRect.Height) /
new Vector2(currentScreenSpaceView.Width, currentScreenSpaceView.Height);
// Store new screen space
currentScreenSpaceView = viewPortRect;
// Scale ScreenObjects by ratio
for (int i = 0; i < textDisplays.Count; i++)
{
textDisplays[i].position = textDisplays[i].position * HudScaleMultiplier;
}
for (int i = 0; i < _imageDisplays.Count; i++)
{
_imageDisplays[i].position = _imageDisplays[i].position * HudScaleMultiplier;
}
for (int i = 0; i < imageSpinners.Count; i++)
{
imageSpinners[i].position = imageSpinners[i].position * HudScaleMultiplier;
}
}
}
#endregion
}
}
# region Spinner
/////
///// Add an Image spinner to our ImageDisplay list
/////
///// Image spinner to add
///// Count of image spinners
//public int AddImageSpinner(ImageSpinner_old val)
//{
// this.imageSpinners.Add(val);
// return imageSpinners.Count - 1;
//}
/////
///// Set the image spinner at index location to the next in-line
/////
///// location
//public void SpinnerNext(int index)
//{
// if (index < 0 || index >= this.imageSpinners.Count)
// {
// // Invalid index
// return;
// }
// else
// {
// ImageSpinner_old temp = this.imageSpinners[index];
// temp.next();
// this.imageSpinners[index] = temp;
// }
//}
/////
///// Set the image spinner at index location to the previous inline
/////
///// location
//public void SpinnerBack(int index)
//{
// if (index < 0 || index >= this.imageSpinners.Count)
// {
// // Invalid index
// return;
// }
// else
// {
// ImageSpinner_old temp = this.imageSpinners[index];
// temp.prev();
// this.imageSpinners[index] = temp;
// }
//}
/////
///// Set the active index to val in our image spinner at index
/////
///// location
///// Active value
//public void SpinnerSet(int index, int val)
//{
// if (index < 0 || index >= this.imageSpinners.Count)
// {
// // Invalid index
// return;
// }
// ImageSpinner_old temp = this.imageSpinners[index];
// if (val < 0 || temp.images.Length <= val)
// {
// return;
// }
// else
// {
// temp.activeIndex = val;
// this.imageSpinners[index] = temp;
// }
//}
#endregion
/////
///// Loads the imageDisplay into the imageDisplays list
///// Loads the textDisplay into the textDisplays list
/////
///// XML Node ImageDisplay
//private void LoadDisplays(XmlNode node)
//{
// if (node.Name == "ImageDisplay")
// {
// this.nameID = node.Attributes["nameID"].Value;
// this.texturePath = node.Attributes["texturePath"].Value;
// this.textureImage = Renderer.Dimensions.content.Load(texturePath);
// this.displayLocation = new Vector2(int.Parse(node.Attributes["posX"].Value), int.Parse(node.Attributes["posY"].Value));
// this.newColor = new Color(
// byte.Parse(node.Attributes["colorR"].Value),
// byte.Parse(node.Attributes["colorG"].Value),
// byte.Parse(node.Attributes["colorB"].Value),
// byte.Parse(node.Attributes["colorA"].Value)
// );
// this.toDraw = bool.Parse(node.Attributes["toDraw"].Value);
// this.quadrant = node.Attributes["quadrant"].Value;
// if (quadrant != "null")
// {
// LocationsTranslation(new Vector2(this.textureImage.Width, this.textureImage.Height));
// }
// this.imageReference = node.Attributes["imageReference"].Value;
// this.imageAttribute = node.Attributes["imageAttribute"].Value;
// this.modifier = int.Parse(node.Attributes["modifier"].Value);
// if (imageReference != "null")
// {
// AdjustLocationBasedOnReferenceImage();
// }
// AddImageDisplay(this.textureImage, this.nameID, this.displayLocation,
// this.textureImage.Width, this.textureImage.Height, newColor, this.toDraw);
// }
// if (node.Name == "TextDisplay")
// {
// this.nameID = node.Attributes["nameID"].Value;
// this.textToScreen = node.Attributes["text"].Value;
// this.displayLocation = new Vector2(int.Parse(node.Attributes["posX"].Value), int.Parse(node.Attributes["posY"].Value));
// this.newColor = new Color(
// byte.Parse(node.Attributes["colorR"].Value),
// byte.Parse(node.Attributes["colorG"].Value),
// byte.Parse(node.Attributes["colorB"].Value),
// byte.Parse(node.Attributes["colorA"].Value)
// );
// this.toDraw = bool.Parse(node.Attributes["toDraw"].Value);
// this.imageReference = node.Attributes["imageReference"].Value;
// this.operation = node.Attributes["operation"].Value;
// this.offset = new Vector2(int.Parse(node.Attributes["offsetX"].Value), int.Parse(node.Attributes["offsetY"].Value));
// this.quadrant = node.Attributes["quadrant"].Value;
// if (this.quadrant != "null")
// {
// LocationsTranslation(new Vector2(gameFonts.Arial.MeasureString(this.textToScreen).X, textureImage.Height));
// }
// if (imageReference != "null")
// {
// for (int x = 0; x < imageDisplays.Count; x++)
// {
// if (imageDisplays[x].name == imageReference)
// {
// LocationBasedOnReference(x);
// AddTextDisplay(this.nameID, this.textToScreen, this.displayLocation, this.newColor, this.toDraw);
// }
// }
// }
// else
// {
// AddTextDisplay(this.nameID, this.textToScreen, this.displayLocation, this.newColor, this.toDraw);
// }
// }
//}