//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Engine.UserInterface { #region Using Statements using System; using System.Collections.Generic; 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 DarkWynter.Stream; using DarkWynter.Engine.Globals; using System.ComponentModel; using DarkWynter.Stream.UIInterfacing; using System.Xml; #endregion /// /// Creates, updates, and draws a heads up display on the user's viewport. /// public class HeadsUpDisplay { #region Init and Update // XML Loading variables for HUD private string nameID; private string texturePath; private Vector2 displayLocation = new Vector2(); private bool toDraw; private string imageReference; private string position; private Texture2D HudTexture; private Color newColor; // Text Display specific private string operation; private string textToScreen; private Vector2 offset; private const int MARGIN_WIDTH = 15; private const int SCROLL = 20; private int dialogueBoxIndex; private int playerIndex = 0; 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 HeadsUpDisplay() { playerIndex = 0; CreateHUD(); InitializeDialogControl(); } /// /// Heads Up Display constructor with player index and predefined viewport. /// /// Player this HUD belongs to. public HeadsUpDisplay(int index) { playerIndex = index; CreateHUD(); InitializeDialogControl(); } /// /// Update Hud events. /// public void Update() { UpdateDialogue(); } #endregion #region HUDCreation /// /// Generate the HUD from XML file /// public void CreateHUD() { try { string fileName = System.IO.Directory.GetCurrentDirectory(); fileName += "\\_xml\\LevelSettings\\HUDSettings\\MedullaHUD.xml"; // Load the HUD Images, Text, and Values XmlDocument reader = new XmlDocument(); reader.Load(fileName); XmlNodeList allNodes = reader.ChildNodes; foreach (XmlNode eventNode in allNodes) { if (eventNode.Name == "HUDSettings") { XmlNodeList eventNodes = eventNode.ChildNodes; foreach (XmlNode node in eventNodes) { if (node.Name == "ImageDisplay") { LoadImageDisplays(node); } if (node.Name == "TextDisplay") { LoadTextDisplays(node); } } } } } catch (Exception e) { System.Diagnostics.Debug.WriteLine("Error reading xml"); throw e; } // Once everything is added to the HUD, call resize for correct image locations FindHudMultiplier(); } /// /// Loads the imageDisplay into the imageDisplays list /// /// XML Node ImageDisplay private void LoadImageDisplays(XmlNode node) { this.nameID = node.Attributes["nameID"].Value; this.texturePath = node.Attributes["texturePath"].Value; HudTexture = Statics_Engine.SystemSettings.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.imageReference = node.Attributes["imageReference"].Value; this.position = node.Attributes["position"].Value; if (imageReference != "null") { if (imageReference == "self") { if (position == "height") { displayLocation.Y = displayLocation.Y - (HudTexture.Height + 10); } else if (position == "width") { displayLocation.X = displayLocation.X - (HudTexture.Width / 2); } else if (position == "both") { displayLocation.Y = displayLocation.Y - (HudTexture.Height / 2); displayLocation.X = displayLocation.X - (HudTexture.Width / 2); } AddImageDisplay(this.HudTexture, this.nameID, this.displayLocation, this.HudTexture.Width, this.HudTexture.Height, newColor, this.toDraw); } for (int x = 0; x < imageDisplays.Count; x++) { if (imageDisplays[x].name == imageReference) { if (position != null) { if (position == "width") { displayLocation.X = MARGIN_WIDTH + imageDisplays[x].width; } else if (position == "height") { displayLocation.Y = imageDisplays[x].height; } else if (position == "both") { displayLocation.X = MARGIN_WIDTH + imageDisplays[x].width; displayLocation.Y = imageDisplays[x].height; } } AddImageDisplay(this.HudTexture, this.nameID, this.displayLocation, this.HudTexture.Width, this.HudTexture.Height, newColor, this.toDraw); } } } else { AddImageDisplay(this.HudTexture, this.nameID, this.displayLocation, this.HudTexture.Width, this.HudTexture.Height, newColor, this.toDraw); } } /// /// Loads the textDisplay into the textDisplays list /// /// XML Node TextDisplay private void LoadTextDisplays(XmlNode node) { 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)); if (imageReference != "null") { for (int x = 0; x < imageDisplays.Count; x++) { if (imageDisplays[x].name == imageReference) { if (operation != "null") { if (operation == "add") { displayLocation = imageDisplays[x].position + offset; } else if (operation == "subtract") { displayLocation = imageDisplays[x].position - offset; } else if (operation == "multiply") { displayLocation = imageDisplays[x].position * offset; } else if (operation == "divide") { displayLocation = imageDisplays[x].position / offset; } } AddTextDisplay(this.nameID, this.textToScreen, this.displayLocation, this.newColor, this.toDraw); } } } else { AddTextDisplay(this.nameID, this.textToScreen, this.displayLocation, this.newColor, this.toDraw); } } private void FindHudMultiplier() { if (Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.GAME_MODE) { Vector2 currentDimensions = new Vector2(1280, 1024); if (currentDimensions != Statics_Engine.LevelSettings.ViewportSize) { // Determine multiplier Vector2 HUDScaleMultiplier = currentDimensions / Statics_Engine.LevelSettings.ViewportSize; //// Resize based on percentage of FULL screen viewport size Resize(HUDScaleMultiplier); Statics_Engine.LevelSettings.ViewportSize = currentDimensions; } } } #endregion #region Dialogue Controls /// /// Inits the dialogue control system /// public void InitializeDialogControl() { for (int x = 0; x < imageDisplays.Count; x++) { if (imageDisplays[x].name == "dialogueBox") { dialogueBoxIndex = x; } } for (int x = 0; x < textDisplays.Count; x++) { if (textDisplays[x].name == "speakerText") { speakerTextIndex = x; } if (textDisplays[x].name == "dialogueText") { dialogueTextIndex = x; } } imageDisplays[dialogueBoxIndex].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[dialogueBoxIndex].visible = true; textDisplays[speakerTextIndex].text = speaker; textDisplays[speakerTextIndex].visible = true; textDisplays[dialogueTextIndex].text = message; textDisplays[dialogueTextIndex].visible = true; } /// /// Removes the dialogue from the HUD /// public void RemoveDialog() { imageDisplays[dialogueBoxIndex].visible = false; textDisplays[speakerTextIndex].text = "ERROR"; textDisplays[speakerTextIndex].visible = false; textDisplays[speakerTextIndex].color = Color.White; textDisplays[dialogueTextIndex].text = "YOU SHOULDN'T EVER SEE THIS"; textDisplays[dialogueTextIndex].visible = false; textDisplays[dialogueTextIndex].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[dialogueBoxIndex].stopWatch.IsRunning) { displayLength = limitMilli; imageDisplays[dialogueBoxIndex].stopWatch.Start(); } else { displayLength = limitMilli; imageDisplays[dialogueBoxIndex].stopWatch.Reset(); } ShowDialog(backgroundImage, speaker, message); } /// /// Removes dialogue once time limit expires /// public void UpdateDialogue() { //Remove dialogue once the limit has passed if (imageDisplays[dialogueBoxIndex].stopWatch.ElapsedMilliseconds >= displayLength) { RemoveDialog(); imageDisplays[dialogueBoxIndex].stopWatch.Reset(); displayLength = 0; } } #endregion #region Add images/text to HUD and helper methods /// /// 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 = Statics_Stream.Fonts.Arial.MeasureString(text); temp.width = (int)(size.X); temp.height = (int)(size.Y); temp.position = position; temp.color = color; temp.visible = draw; textDisplays.Add(temp); return textDisplays.Count - 1; } /// /// 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; _imageDisplays.Add(temp); } /// /// Resizes the HUD based on viewport change /// /// The ratio between old viewport and resized viewport public void Resize(Vector2 HudScaleMultiplier) { 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 Draw functions /// /// Default Draw function. /// /// SpriteBatch used to draw used to draw. public void Draw(SpriteBatch spriteBatch) { Draw(spriteBatch, 0, 0); } /// /// 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) { 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, element.Size.Width, element.Size.Height), element.Source, element.color); } } foreach (ImageSpinner_old elementBig in imageSpinners) { if (elementBig.visible == true) { //ImageDisplay element = elementBig.images[elementBig.activeIndex]; //spriteBatch.Draw(element.image, // new Rectangle((int)element.position.X + xoffset, // (int)element.position.Y + yoffset, // element.width, // element.height), // new Rectangle(0, 0, (int)(element.image.Width * element.xScale), (int)(element.image.Height * element.yScale)), // element.color); } } foreach (TextDisplay element in textDisplays) { if (element.visible) { spriteBatch.DrawString(Statics_Stream.Fonts.Arial, element.text, element.position, element.color); } } } #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