//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------
namespace DarkWynter.Engine.Menus
{
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using DarkWynter.Engine.Globals;
using DarkWynter.Stream;
#endregion
///
/// Wrapper class for Game Menu Elements.
///
public class GameMenuElement
{
///
/// Game menu title.
///
protected string title = "Untitled";
///
/// Element type from Enums_Engine.MenuElementType.
///
protected Enums_Engine.MenuElementType type;
///
/// Current visibility state of element.
///
protected bool visible = true;
///
/// Current x scale of element.
///
protected float scaleX = 1.0f;
///
/// Current y scale of element.
///
protected float scaleY = 1.0f;
///
/// Font used in this element.
///
protected SpriteFont font = Statics_Stream.Fonts.ComicSans;
///
/// Set to red by default, to provide easily noticable default color.
///
protected Color color = Color.Red;
///
/// Game Menu Element constructor.
///
public GameMenuElement()
{
type = Enums_Engine.MenuElementType.NONE;
}
///
/// Accessor for element type.
///
/// This element's type.
public Enums_Engine.MenuElementType GetElementType()
{
return type;
}
///
/// Sets the element's scale.
///
/// X scale value
/// Y scale value
public void SetScale(float scaleX, float scaleY)
{
this.scaleX = scaleX;
this.scaleY = scaleY;
}
///
/// Gets the color of the SpriteFont
///
///
public Color GetColor()
{
return color;
}
public void SetColor(Color fontColor)
{
color = fontColor;
}
///
/// Gets the element's current font.
///
/// Return's current spritefont
public SpriteFont GetFont()
{
return font;
}
///
/// Sets the element's current font.
///
/// SpriteFont to use.
public void SetFont(SpriteFont font)
{
this.font = font;
}
///
/// Gets the element's current x scale.
///
/// Current X scale of element..
public float GetScaleX()
{
return scaleX;
}
///
/// Gets the element's current y scale.
///
/// Current Y scale of element.
public float GetScaleY()
{
return scaleY;
}
///
/// Sets the element's title.
///
/// Title of element.
public void SetTitle(string title)
{
this.title = title;
}
///
/// Gets the element's title.
///
/// Title of element.
public string GetTitle()
{
return title;
}
///
/// Hides this element from view.
///
public void Hide()
{
visible = false;
}
///
/// Makes this element visible.
///
public void Show()
{
visible = true;
}
///
/// Checks to see if element is currently visible.
///
/// True if visible
public bool isVisible()
{
return visible;
}
}
///
/// 2D Label
///
public class GameMenuLabel : GameMenuElement
{
///
/// Game Menu Lable constructor
///
public GameMenuLabel()
{
type = Enums_Engine.MenuElementType.LABEL;
}
///
/// Game Menu Lable constructor with title.
///
/// Title of the element.
public GameMenuLabel(string title)
{
type = Enums_Engine.MenuElementType.LABEL;
this.title = title;
}
///
/// Game Menu Lable constructor with title.
///
/// Title of the element.
public GameMenuLabel(string title, Color textColor)
{
type = Enums_Engine.MenuElementType.LABEL;
this.color = textColor;
this.title = title;
}
}
///
/// 2D Image display
///
public class GameMenuRandomImageDisplay : GameMenuElement
{
private List images = new List();
private int selectedIndex = 0;
private List used = new List();
Random rand = new Random();
///
/// Random Image Display constructor.
///
public GameMenuRandomImageDisplay()
{
type = Enums_Engine.MenuElementType.IMAGE_DISPLAY;
}
///
/// Random Image Display constructor with title.
///
/// Title of the Random Image Display.
public GameMenuRandomImageDisplay(string title)
{
type = Enums_Engine.MenuElementType.IMAGE_DISPLAY;
this.title = title;
}
///
/// Add's an image to the Random Image Display.
///
/// Image to add.
public void AddImage(Texture2D img)
{
images.Add(img);
}
///
/// Selects a random image to use.
///
public void RandomIndex()
{
if (used.Count == images.Count)
{
used.Clear();
}
do
{
selectedIndex = rand.Next(images.Count);
}
while (used.Contains(selectedIndex));
used.Add(selectedIndex);
}
///
/// Gets the current image being used.
///
/// Image currently being used.
public Texture2D GetCurrentTexture()
{
if (selectedIndex >= 0 && selectedIndex < images.Count)
{
return images[selectedIndex];
}
return null;
}
}
///
/// 2D Button
///
public class GameMenuButton : GameMenuElement
{
///
/// Game Menu Button constructor.
///
public GameMenuButton()
{
type = Enums_Engine.MenuElementType.BUTTON;
}
///
/// Game Menu Button with title.
///
/// Title of this Game Menu Button.
public GameMenuButton(string title)
{
this.title = title;
type = Enums_Engine.MenuElementType.BUTTON;
}
}
///
/// 2D Renderable
///
public class GameMenuValueInput : GameMenuElement
{
private int value = 0;
private int maxValue = 0;
private int minValue = 0;
private int valueIncrement = 1;
private float valueRatio = 0.0f;
///
/// Constructor for Game Menu Value Input.
///
public GameMenuValueInput()
{
type = Enums_Engine.MenuElementType.VALUE;
}
///
/// Constructor for Game Menu Value Input with predefined values.
///
/// Title of this component.
/// Minimum value of this component.
/// Maximum value of this component.
/// Initial/Default value of this component.
/// Increment rate of this componenet.
public GameMenuValueInput(string title, int minValue, int maxValue, int defaultValue, int increment)
{
this.title = title;
this.minValue = minValue;
this.maxValue = maxValue;
this.value = defaultValue;
this.valueIncrement = increment;
valueRatio = (float)this.value / (float)(this.maxValue - this.minValue);
type = Enums_Engine.MenuElementType.VALUE;
}
///
/// Get current value of componenet.
///
/// Current value.
public int GetValue()
{
return value;
}
///
/// Set range of this componenet.
///
/// Minimum allowed value.
/// Maximum allowed value.
public void SetRange(int min, int max)
{
maxValue = max;
minValue = min;
UpdateValueRatio();
}
///
/// Manually set the value of this component.
///
/// Value to set this component to.
public void SetValue(int val)
{
if (val <= maxValue && val >= minValue)
{
value = val;
UpdateValueRatio();
}
}
private void UpdateValueRatio()
{
if (maxValue == minValue)
{
valueRatio = 1.0f;
}
else
{
valueRatio = ((float)this.value - this.minValue) / ((float)(this.maxValue - this.minValue));
}
}
///
/// Ratio between minumum and maximum value of this component.
///
/// Ratio of max and min values.
public float GetValueRatio()
{
return valueRatio;
}
///
/// Increment value of component using predefined increment amount.
///
public void Increment()
{
value += valueIncrement;
if (value > maxValue)
{
value = maxValue;
}
UpdateValueRatio();
}
///
/// Decrement value of component using predefined increment amount.
///
public void Decrement()
{
value -= valueIncrement;
if (value < minValue)
{
value = minValue;
}
UpdateValueRatio();
}
}
///
/// 2D Value Scroller
///
public class GameMenuOption : GameMenuElement
{
private List options = new List();
private int activeOptionIndex = 0;
///
/// Constructor for Option selector.
///
public GameMenuOption()
{
type = Enums_Engine.MenuElementType.OPTION;
}
///
/// Constructor for Option selector with title.
///
/// Title of this component.
public GameMenuOption(string title)
{
this.title = title;
type = Enums_Engine.MenuElementType.OPTION;
}
///
/// Add an option to this option selector.
///
/// Displayed text.
public void AddOption(string option)
{
options.Add(option);
}
///
/// Add a list of options to this option selector.
///
/// List of displayed text.
public void SetOption(List optionList)
{
options = optionList;
}
///
/// Set currently displayed option text.
///
/// Index of option to display.
public void SetCurrentIndex(int index)
{
activeOptionIndex = index;
}
///
/// Select the previous option in the list.
///
public void PreviousOption()
{
activeOptionIndex--;
if (activeOptionIndex < 0)
{
activeOptionIndex = 0;
}
}
///
/// Select the next option in the list.
///
public void NextOption()
{
activeOptionIndex++;
if (activeOptionIndex >= options.Count)
{
activeOptionIndex = options.Count - 1;
}
}
///
/// Get the current option's text.
///
/// Current option's text.
public string GetActiveOption()
{
return options[activeOptionIndex];
}
///
/// Get the current option's index.
///
/// Current option's index.
public int GetActiveIndex()
{
return activeOptionIndex;
}
}
///
/// Image with multiple selectable components.
///
public class GameMenuImageScroller : GameMenuElement
{
///
/// An image scrolling item
///
public struct ImageScrollItem
{
///
/// Inactive image
///
public Texture2D offImage;
///
/// Active image
///
public Texture2D onImage;
///
/// Screen X position of image
///
public int x;
///
/// Screen Y position of image
///
public int y;
///
/// Name of the Item
///
public string name;
};
private int maxVisibleAtATime = 0;
List items = new List();
private int activeItemIndex = 0;
///
/// Default Constructor
///
public GameMenuImageScroller()
{
type = Enums_Engine.MenuElementType.IMAGE_SCROLL;
}
///
/// Constructor
///
/// The title of the Menu
/// The number of visible lines?
public GameMenuImageScroller(string title, int numVisible)
{
maxVisibleAtATime = numVisible;
this.title = title;
type = Enums_Engine.MenuElementType.IMAGE_SCROLL;
}
private void AddNew(string name, Texture2D onImage, Texture2D offImage, int x, int y)
{
ImageScrollItem item = new ImageScrollItem();
item.name = name;
item.onImage = onImage;
item.offImage = offImage;
item.x = x;
item.y = y;
items.Add(item);
}
private void AddNew(string name, Texture2D onImage, Texture2D offImage)
{
ImageScrollItem item = new ImageScrollItem();
item.name = name;
item.onImage = onImage;
item.offImage = offImage;
item.x = -1;
item.y = -1;
items.Add(item);
}
///
/// Retrieve the Item at index location
///
/// Location
/// ImageScrollItem
public ImageScrollItem GetItemAt(int index)
{
if (index >= 0 && index < items.Count)
{
return items[index];
}
return new ImageScrollItem();
}
///
/// Returns the number of items in the Menu
///
/// Number of items in the Menu
public int GetNumItems()
{
return items.Count;
}
///
/// Returns the maximum number of visible items in a Menu
///
/// Maximum number of visible items in a Menu
public int GetMaxItemsVisible()
{
return maxVisibleAtATime;
}
private void Clear()
{
activeItemIndex = 0;
items.Clear();
}
///
/// Sets the previous item as the current one
///
public void PreviousItem()
{
activeItemIndex--;
if (activeItemIndex < 0)
{
activeItemIndex = items.Count - 1;
}
}
///
/// Sets the next item as the current one
///
public void NextItem()
{
activeItemIndex++;
if (activeItemIndex >= items.Count)
{
activeItemIndex = 0;
}
}
private ImageScrollItem GetActiveItem()
{
return items[activeItemIndex];
}
///
/// Returns the index of the active item
///
/// Index of active item
public int GetActiveIndex()
{
return activeItemIndex;
}
///
/// Sets the item at index to the current one
///
/// Location
public void SetCurrentIndex(int index)
{
if (index >= 0 || index < items.Count)
{
activeItemIndex = index;
}
}
}
///
/// GameMenu is used by a GameScreen.
/// It contains a list of GameMenuElements such as Buttons, Options, and Scrollers
/// that are defined by classes that override GameScreen.
///
public class GameMenu
{
private string title = "Untitled Menu";
private List menuElements = new List();
private int selectedElementIndex = 0;
private Vector2 position = new Vector2();
private const int SLIDER_WIDTH = 150;
private const int SLIDER_HEIGHT = 30;
private bool drawMenuTitle = true;
private Texture2D sliderBackground;
///
/// Constructor
///
/// Name of the Menu
/// Screen X position
/// Screen Y positiong
public GameMenu(string title, float positionX, float positionY)
{
this.title = title;
position.X = positionX;
position.Y = positionY;
sliderBackground = Statics_Engine.SystemSettings.content.Load("Content/_textures/SliderImproved");
}
///
/// Sets whether the menu is drawn or not
///
/// Yes or No
public void SetDrawMenuTitle(bool draw)
{
drawMenuTitle = draw;
}
///
/// Sets the menu title
///
/// Name
public void SetTitle(string title)
{
this.title = title;
}
///
/// Sets the position where the menu will be drawn
///
/// X
/// Y
public void SetPosition(float x, float y)
{
position.X = x;
position.Y = y;
}
///
/// Adds a new menu Button
///
/// To draw or not to draw
/// Name
public void AddMenuButton(bool visible, string title)
{
AddMenuButton(title);
if (!visible)
{
GetMenuElement(title).Hide();
}
}
///
/// Adds a new menu Button
///
/// Name
public void AddMenuButton(string title)
{
menuElements.Add(new GameMenuButton(title));
}
///
/// Adds a new Menu Option Item
///
/// To draw or not to draw
/// Name
/// String array of options
public void AddMenuOption(bool visible, string title, params string[] options)
{
AddMenuOption(title,options);
if (!visible)
{
GetMenuElement(title).Hide();
}
}
///
/// Adds a new Menu Option Item
///
/// Name
/// String array of options
public void AddMenuOption(string title, params string[] options)
{
GameMenuOption element = new GameMenuOption(title);
foreach (string s in options)
{
element.AddOption(s);
}
menuElements.Add(element);
}
///
/// Adds a new image display which randomly displays a different image
///
/// Name
/// Array of images
public void AddRandomImageDisplay(string title, params Texture2D[] images)
{
GameMenuRandomImageDisplay element = new GameMenuRandomImageDisplay(title);
foreach (Texture2D image in images)
{
element.AddImage(image);
}
menuElements.Add(element);
}
///
/// Sets the list of options for a particular Menu option item
///
/// New list of options
/// Index of menu option item
public void SetMenuOption(List optionList, int optionNumber)
{
GameMenuOption menuOptions = (GameMenuOption)menuElements[optionNumber];
menuOptions.SetOption(optionList);
}
private void AddValueInput(bool visible, string title, int minValue, int maxValue, int defaultValue, int increment)
{
AddValueInput(title, minValue, maxValue, defaultValue, increment);
if (!visible)
{
GetMenuElement(title).Hide();
}
}
///
/// Adds a new Menu value-based item
///
/// Name
/// Minimum Value
/// Maximum Value
/// Default value
/// Increments
public void AddValueInput(string title, int minValue, int maxValue, int defaultValue, int increment)
{
GameMenuValueInput valueInput = new GameMenuValueInput(title, minValue, maxValue, defaultValue, increment);
menuElements.Add(valueInput);
}
///
/// Adds a new Menu image scroller item
///
/// Name
/// Number of visible lines?
public void AddImageScroller(string title, int numVisible)
{
GameMenuImageScroller element = new GameMenuImageScroller(title, numVisible);
menuElements.Add(element);
}
///
/// Adds a new Menu Label item
///
/// Name
public void AddLabel(string title, Color textColor)
{
GameMenuLabel label = new GameMenuLabel(title, textColor);
menuElements.Add(label);
}
///
/// Adds a new Menu Label item
///
/// Name
public void AddLabel(string title)
{
GameMenuLabel label = new GameMenuLabel(title);
menuElements.Add(label);
}
///
/// Sets the current menu element to the previous menu element
///
public void PreviousMenuElement()
{
selectedElementIndex--;
if (selectedElementIndex < 0)
{
selectedElementIndex = 0;
}
if (GetActiveMenuElement().isVisible() == false)
{
PreviousMenuElement();
}
if (GetActiveMenuElement().GetElementType() == Enums_Engine.MenuElementType.LABEL)
{
if (selectedElementIndex == 0)
{
NextMenuElement();
}
else
{
PreviousMenuElement();
}
}
}
///
/// Sets the current menu element to the next menu element
///
public void NextMenuElement()
{
selectedElementIndex++;
if (selectedElementIndex >= menuElements.Count)
{
selectedElementIndex = menuElements.Count - 1;
}
if (GetActiveMenuElement().isVisible() == false)
{
NextMenuElement();
}
if (GetActiveMenuElement().GetElementType() == Enums_Engine.MenuElementType.LABEL)
{
if (selectedElementIndex == menuElements.Count - 1)
{
PreviousMenuElement();
}
else
{
NextMenuElement();
}
}
}
///
/// Returns the Name of the current Game Menu
///
/// String name of current Game Menu
public string GetTitle()
{
return title;
}
///
/// Returns the current active menu element
///
/// Menu Element
public GameMenuElement GetActiveMenuElement()
{
return menuElements[selectedElementIndex];
}
///
/// Returns the index of the current active menu element
///
/// Index of the current active menu element
public int GetActiveIndex()
{
return selectedElementIndex;
}
///
/// Returns the Menu element at index
///
/// Index of element to retrieve
/// Menu Element
public GameMenuElement GetMenuElement(int index)
{
return menuElements[index];
}
///
/// Returns the first Menu element which has a matching title
///
/// Search name
/// Menu Element
public GameMenuElement GetMenuElement(string title)
{
foreach (GameMenuElement element in menuElements)
{
if (element.GetTitle() == title)
{
return element;
}
}
return new GameMenuElement();
}
///
/// Returns the first Menu element found with a matching title after the starting index
///
/// Search name
/// Search index start
/// Menu Element
public GameMenuElement GetMenuElement(string title, int fromIndex)
{
for (int i = fromIndex; i < menuElements.Count; i++)
{
if (menuElements[i].GetTitle() == title)
{
return menuElements[i];
}
}
return new GameMenuElement();
}
///
/// Sets the font for all menu items
///
/// Font
public void SetFont(SpriteFont font)
{
for (int i = 0; i < menuElements.Count; i++)
{
menuElements[i].SetFont(font);
}
}
///
/// Draw function
///
/// Spritebatch
public void Draw(SpriteBatch spriteBatch)
{
float yPosition = position.Y;
int titleLength = 0;
float scaleX = (Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH / 1280.0f);
float scaleY = (Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT / 1024.0f);
// Draw Header
if (drawMenuTitle)
{
spriteBatch.DrawString(Statics_Stream.Fonts.ComicSans, title, new Vector2(position.X, position.Y), Color.White);
Vector2 size = Statics_Stream.Fonts.ComicSans.MeasureString(title);
//Extra padding below the big font
yPosition += size.Y;
}
// Draw menu elements
for (int i = 0; i < menuElements.Count; i++)
{
if (menuElements[i].isVisible() == true)
{
spriteBatch.DrawString(menuElements[i].GetFont(), menuElements[i].GetTitle(), new Vector2(position.X, yPosition), menuElements[i].GetColor());
Vector2 stringSize = menuElements[i].GetFont().MeasureString(menuElements[i].GetTitle());
titleLength = (int)(stringSize.X) + 10;
// Option Selectors
if (menuElements[i].GetElementType() == Enums_Engine.MenuElementType.OPTION)
{
GameMenuOption option = (GameMenuOption)menuElements[i];
spriteBatch.DrawString(menuElements[i].GetFont(), option.GetActiveOption(), new Vector2(position.X + titleLength, yPosition), Color.White);
}
// Value Selectors
if (menuElements[i].GetElementType() == Enums_Engine.MenuElementType.VALUE)
{
GameMenuValueInput valueSlider = (GameMenuValueInput)menuElements[i];
spriteBatch.Draw(sliderBackground,
new Rectangle((int)(position.X) + titleLength, (int)(yPosition), SLIDER_WIDTH, SLIDER_HEIGHT),
Color.Honeydew);
//Draw the actual slider value here
spriteBatch.Draw(sliderBackground,
new Rectangle((int)(position.X) + titleLength,
(int)(yPosition),
(int)(SLIDER_WIDTH * valueSlider.GetValueRatio()),
SLIDER_HEIGHT),
Color.DarkRed);
spriteBatch.DrawString(menuElements[i].GetFont(), "" + valueSlider.GetValue(), new Vector2(position.X + titleLength + (SLIDER_WIDTH / 2), yPosition - 3), Color.Black);
}
// Image Displays
if (menuElements[i].GetElementType() == Enums_Engine.MenuElementType.IMAGE_DISPLAY)
{
GameMenuRandomImageDisplay imageDisplay = (GameMenuRandomImageDisplay)menuElements[i];
Texture2D image = imageDisplay.GetCurrentTexture();
//yPosition += (160 * scaleY);
if (image != null)
{
spriteBatch.Draw(image, new Rectangle((int)(position.X),
(int)(yPosition),
(int)(image.Width * imageDisplay.GetScaleX() * scaleX),
(int)(image.Height * imageDisplay.GetScaleY() * scaleY)), Color.White);
yPosition += (image.Height + 50) * scaleY;
}
}
#region Image Scrollers
if (menuElements[i].GetElementType() == Enums_Engine.MenuElementType.IMAGE_SCROLL)
{
GameMenuImageScroller scroller = (GameMenuImageScroller)menuElements[i];
int numItems = scroller.GetNumItems();
int maxItems = scroller.GetMaxItemsVisible();
int activeIndex = scroller.GetActiveIndex();
yPosition += 8;
//if the window is smaller than the list.. start with the active one
for (int index = (maxItems < numItems) ? activeIndex : 0;
index < ((maxItems < numItems)? activeIndex+maxItems : maxItems); index++)
{
if (index >= numItems)
{
break;
}
GameMenuImageScroller.ImageScrollItem item = scroller.GetItemAt(index);
float x, y;
if (item.x == -1){x = position.X;}
else{x = item.x;}
if (item.y == -1){y = yPosition;}
else{y = item.y;}
if (scroller.GetActiveIndex() == index)
{
if (item.onImage != null)
{
// Draw Selected Button Image
spriteBatch.Draw(item.onImage, new Rectangle((int)(x),
(int)(y),
(int)(item.onImage.Width * scroller.GetScaleX() * scaleX),
(int)(item.onImage.Height * scroller.GetScaleY() * scaleY)), Color.White);
}
}
else
{
if (item.offImage != null)
{
// Draw Deselected Button Image
spriteBatch.Draw(item.offImage, new Rectangle((int)(x),
(int)(y),
(int)(item.offImage.Width * scroller.GetScaleX() * scaleX),
(int)(item.offImage.Height * scroller.GetScaleY() * scaleY)), Color.White);
}
}
int heightOffset = 0;
if (item.offImage != null)
{
heightOffset = item.offImage.Height;
}
yPosition += (heightOffset + 50) * scaleY;
}
}
#endregion
yPosition += stringSize.Y + 20;
}
}
}
}
}