//--------------------------------------------------------------------------------------------------------------------------------------------------- // // 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); // } // } //}