Replaced color usage with OpenTK's implementation.
This commit is contained in:
85
RecrownedAthenaeum/Graphics/UI/Modular/Modules/Image.cs
Normal file
85
RecrownedAthenaeum/Graphics/UI/Modular/Modules/Image.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using RecrownedAthenaeum.Graphics.Render;
|
||||
using RecrownedAthenaeum.Types;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using System;
|
||||
|
||||
namespace RecrownedAthenaeum.Graphics.UI.Modular.Modules
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a texture with more information.
|
||||
/// </summary>
|
||||
public class Image : UIModule, ISpecialDrawable
|
||||
{
|
||||
/// <summary>
|
||||
/// The rotation of the image.
|
||||
/// </summary>
|
||||
public float rotation = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The texture to be rendered.
|
||||
/// </summary>
|
||||
public Texture2D texture;
|
||||
|
||||
/// <summary>
|
||||
/// Scale of of the X axis.
|
||||
/// </summary>
|
||||
public float ScaleX { get { return (float)Width / texture.Width; } set { Width = (int)(texture.Width * value); } }
|
||||
|
||||
/// <summary>
|
||||
/// Scale of the Y axis.
|
||||
/// </summary>
|
||||
public float ScaleY { get { return (float)Height / texture.Height; } set { Height = (int)(texture.Height * value); } }
|
||||
|
||||
/// <summary>
|
||||
/// Sets scale of X and Y.
|
||||
/// </summary>
|
||||
public float Scale { set { ScaleY = value; ScaleX = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an image given a texture.
|
||||
/// </summary>
|
||||
/// <param name="texture">Texture to use.</param>
|
||||
public Image(Texture2D texture)
|
||||
{
|
||||
this.texture = texture ?? throw new ArgumentException("Image requires a texture.");
|
||||
SetPositionAndDimensions(texture.Bounds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the image with default values.
|
||||
/// </summary>
|
||||
/// <param name="batch">The batch to use.</param>
|
||||
public override void Draw(ConsistentSpriteBatch batch)
|
||||
{
|
||||
batch.Draw(texture, new Rectangle(X, Y, Width, Height), null, color, rotation, origin, SpriteEffects.None, 0f);
|
||||
base.Draw(batch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the image with more options.
|
||||
/// </summary>
|
||||
/// <param name="spriteBatch">Batch used.</param>
|
||||
/// <param name="destination">Where to draw texture to.</param>
|
||||
/// <param name="color">The color tint to use.</param>
|
||||
/// <param name="rotation">Rotation of image.</param>
|
||||
/// <param name="origin">Origin for the rotation.</param>
|
||||
public void Draw(ConsistentSpriteBatch spriteBatch, Rectangle destination, Color4 color, float rotation = 0, Vector2 origin = default(Vector2))
|
||||
{
|
||||
this.color = color;
|
||||
this.rotation = rotation;
|
||||
this.origin = origin;
|
||||
SetPositionAndDimensions(destination);
|
||||
Draw(spriteBatch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Center's the origin to the middle of the dimensions of the texture.
|
||||
/// </summary>
|
||||
public override void CenterOrigin()
|
||||
{
|
||||
origin.X = texture.Bounds.Width / 2f;
|
||||
origin.Y = texture.Bounds.Height / 2f;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,155 @@
|
||||
using RecrownedAthenaeum.Types;
|
||||
using RecrownedAthenaeum.Input;
|
||||
using RecrownedAthenaeum.Graphics.UI.SkinSystem.Definitions;
|
||||
using RecrownedAthenaeum.Graphics.UI.SkinSystem;
|
||||
using RecrownedAthenaeum.Graphics.Render;
|
||||
|
||||
namespace RecrownedAthenaeum.Graphics.UI.Modular.Modules.Interactive
|
||||
{
|
||||
/// <summary>
|
||||
/// Function to be called when button is clicked.
|
||||
/// </summary>
|
||||
/// <param name="button">The button that was clicked.</param>
|
||||
public delegate void Clicked(Button button);
|
||||
|
||||
/// <summary>
|
||||
/// A very primitive button containing all the basic functions.
|
||||
/// </summary>
|
||||
public class Button : UIModule
|
||||
{
|
||||
private ButtonSkinDefinition skinDefinition;
|
||||
private ISpecialDrawable downTexture, upTexture, highlightedTexture, disabledTexture;
|
||||
/// <summary>
|
||||
/// Click event listeners.
|
||||
/// </summary>
|
||||
public event Clicked Listeners;
|
||||
private bool pressed;
|
||||
/// <summary>
|
||||
/// Whether or not this button should be currently disabled.
|
||||
/// </summary>
|
||||
public bool disabled = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this button is currently being hovered on.
|
||||
/// </summary>
|
||||
public bool Highlighted { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs this button using <see cref="ISpecialDrawable"/>s for the different states it could be in.
|
||||
/// </summary>
|
||||
/// <param name="down">Button being pressed.</param>
|
||||
/// <param name="up">Button not being pressed.</param>
|
||||
/// <param name="disabled">Disabled button.</param>
|
||||
/// <param name="selected">Button being highlighted.</param>
|
||||
public Button(ISpecialDrawable down, ISpecialDrawable up, ISpecialDrawable disabled = null, ISpecialDrawable selected = null)
|
||||
{
|
||||
this.downTexture = down;
|
||||
this.upTexture = up;
|
||||
this.disabledTexture = disabled;
|
||||
this.highlightedTexture = selected;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs this button using the skin system.
|
||||
/// </summary>
|
||||
/// <param name="skin">The skin containing the information of the textures and design to follow.</param>
|
||||
/// <param name="definitionName">The name of the definition in the skin. Can be null to select the default.</param>
|
||||
public Button(ISkin skin, string definitionName = null)
|
||||
{
|
||||
skinDefinition = skin.ObtainDefinition<ButtonSkinDefinition>(definitionName);
|
||||
downTexture = skin.GetTextureAtlasRegion(skinDefinition.downRegion, true);
|
||||
upTexture = skin.GetTextureAtlasRegion(skinDefinition.upRegion, true);
|
||||
disabledTexture = skin.GetTextureAtlasRegion(skinDefinition.disabledRegion);
|
||||
highlightedTexture = skin.GetTextureAtlasRegion(skinDefinition.selectedRegion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a button using a definition.
|
||||
/// </summary>
|
||||
/// <param name="skin">The skin the definition is defined in.</param>
|
||||
/// <param name="skinDefinition">The definition itself.</param>
|
||||
public Button(ISkin skin, ButtonSkinDefinition skinDefinition) :
|
||||
this(skin.GetTextureAtlasRegion(skinDefinition.downRegion, true),
|
||||
skin.GetTextureAtlasRegion(skinDefinition.upRegion, true),
|
||||
skin.GetTextureAtlasRegion(skinDefinition.disabledRegion),
|
||||
skin.GetTextureAtlasRegion(skinDefinition.selectedRegion))
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Draws the button.
|
||||
/// </summary>
|
||||
/// <param name="batch">Batch used to draw the button.</param>
|
||||
public override void Draw(ConsistentSpriteBatch batch)
|
||||
{
|
||||
if (disabled)
|
||||
{
|
||||
disabledTexture?.Draw(batch, Boundaries, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
downTexture.Draw(batch, Boundaries, color);
|
||||
}
|
||||
else if (Highlighted)
|
||||
{
|
||||
highlightedTexture?.Draw(batch, Boundaries, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
upTexture.Draw(batch, Boundaries, color);
|
||||
}
|
||||
}
|
||||
|
||||
base.Draw(batch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the mouse changes state.
|
||||
/// </summary>
|
||||
/// <param name="state">The new state.</param>
|
||||
/// <returns>Whether or not to continue calling the next mouse change listener.</returns>
|
||||
public sealed override bool MouseStateChanged(MouseState state)
|
||||
{
|
||||
if (InputUtilities.MouseWithinBoundries(Boundaries))
|
||||
{
|
||||
if (state.LeftButton == ButtonState.Pressed)
|
||||
{
|
||||
pressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pressed = false;
|
||||
}
|
||||
if (InputUtilities.MouseClicked())
|
||||
{
|
||||
OnClick();
|
||||
}
|
||||
Highlighted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Highlighted = false;
|
||||
pressed = false;
|
||||
}
|
||||
|
||||
return base.MouseStateChanged(state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the state of the keyboard changes.
|
||||
/// </summary>
|
||||
/// <param name="state">The new state.</param>
|
||||
/// <returns>Whether or not the next keyboard change listener should be called.</returns>
|
||||
public sealed override bool KeyboardStateChanged(KeyboardState state)
|
||||
{
|
||||
return base.KeyboardStateChanged(state);
|
||||
}
|
||||
|
||||
internal void OnClick()
|
||||
{
|
||||
Listeners?.Invoke(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
using RecrownedAthenaeum.Graphics.Render;
|
||||
using OpenTK.Graphics;
|
||||
using RecrownedAthenaeum.Graphics.UI.SkinSystem;
|
||||
using RecrownedAthenaeum.Graphics.UI.SkinSystem.Definitions;
|
||||
|
||||
namespace RecrownedAthenaeum.Graphics.UI.Modular.Modules.Interactive
|
||||
{
|
||||
/// <summary>
|
||||
/// Button that holds a string.
|
||||
/// </summary>
|
||||
public class TextButton : Button
|
||||
{
|
||||
/// <summary>
|
||||
/// The text that is used to display the string.
|
||||
/// </summary>
|
||||
public readonly Text text;
|
||||
|
||||
/// <summary>
|
||||
/// The color the font should be rendered in.
|
||||
/// </summary>
|
||||
public Color4 FontColor { get { return text.color; } set { text.color = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs text button with the positions represented by <see cref="ISpecialDrawable"/>
|
||||
/// </summary>
|
||||
/// <param name="text">The string representing the text to be displayed.</param>
|
||||
/// <param name="font">The font to be used to display the text.</param>
|
||||
/// <param name="down">What to draw as button is pushed down.</param>
|
||||
/// <param name="up">What to draw as button is not pushed.</param>
|
||||
/// <param name="disabled">What to draw as button is disabled.</param>
|
||||
/// <param name="selected">What to draw as button is selected.</param>
|
||||
public TextButton(string text, SpriteFont font, ISpecialDrawable down, ISpecialDrawable up, ISpecialDrawable disabled = null, ISpecialDrawable selected = null) : base(down, up, disabled, selected)
|
||||
{
|
||||
this.text = new Text(font, text);
|
||||
this.text.autoScale = true;
|
||||
this.text.centered = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a text button using a skin and definition.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to display.</param>
|
||||
/// <param name="font">The font to be used.</param>
|
||||
/// <param name="skin">The skin to use.</param>
|
||||
/// <param name="definitionName">Name of the definition for this type in the skin given.</param>
|
||||
public TextButton(string text, SpriteFont font, ISkin skin, string definitionName = null) : base(skin, skin.ObtainDefinition<TextButtonSkinDefinition>(definitionName))
|
||||
{
|
||||
TextButtonSkinDefinition skinDefinition = skin.ObtainDefinition<TextButtonSkinDefinition>(definitionName);
|
||||
this.text = new Text(font, text);
|
||||
this.text.autoScale = true;
|
||||
this.text.centered = true;
|
||||
FontColor = skin.GetColor(skinDefinition.fontColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a text button with a given definition.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to be displayed on this button.</param>
|
||||
/// <param name="font">The font to use for this button.</param>
|
||||
/// <param name="skin">The skin the definition is from.</param>
|
||||
/// <param name="skinDefinition">The definition to use.</param>
|
||||
public TextButton(string text, SpriteFont font, ISkin skin, TextButtonSkinDefinition skinDefinition) :
|
||||
this(text,
|
||||
font,
|
||||
skin.GetTextureAtlasRegion(skinDefinition.downRegion, true),
|
||||
skin.GetTextureAtlasRegion(skinDefinition.upRegion, true),
|
||||
skin.GetTextureAtlasRegion(skinDefinition.disabledRegion),
|
||||
skin.GetTextureAtlasRegion(skinDefinition.selectedRegion))
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Updates the text button.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">Snapshot of information about time for game.</param>
|
||||
public override void Update(GameTime gameTime)
|
||||
{
|
||||
text.SetPositionAndDimensions(Boundaries);
|
||||
text.Update(gameTime);
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever game wants to render this button.
|
||||
/// </summary>
|
||||
/// <param name="batch">Batch to use. Batch should already be started.</param>
|
||||
public override void Draw(ConsistentSpriteBatch batch)
|
||||
{
|
||||
base.Draw(batch);
|
||||
text.Draw(batch);
|
||||
}
|
||||
}
|
||||
}
|
206
RecrownedAthenaeum/Graphics/UI/Modular/Modules/Text.cs
Normal file
206
RecrownedAthenaeum/Graphics/UI/Modular/Modules/Text.cs
Normal file
@@ -0,0 +1,206 @@
|
||||
using OpenTK;
|
||||
using RecrownedAthenaeum.Graphics.Render;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace RecrownedAthenaeum.Graphics.UI.Modular.Modules
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents text for the UI.
|
||||
/// </summary>
|
||||
public class Text : UIModule
|
||||
{
|
||||
private SpriteFont font;
|
||||
private float scale = 1f;
|
||||
private Vector2 position;
|
||||
private string originalText;
|
||||
private string displayedText;
|
||||
private Vector2 modifiedTextSize;
|
||||
|
||||
/// <summary>
|
||||
/// Centers the text int bounds.
|
||||
/// </summary>
|
||||
public bool centered;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to try and wrap text automatically. Meaning will check and attempt to wrap every update.
|
||||
/// </summary>
|
||||
public bool autoWrap;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to automatically scale the text every update. Happens after auto wrap if enabled.
|
||||
/// </summary>
|
||||
public bool autoScale;
|
||||
|
||||
/// <summary>
|
||||
/// Should this use ellipses? Will perform this operation before auto wrapping or auto scalling.
|
||||
/// </summary>
|
||||
public bool useEllipses;
|
||||
|
||||
/// <summary>
|
||||
/// The text to use for the ellipsis.
|
||||
/// </summary>
|
||||
public string ellipsis = "...";
|
||||
private string ModifiedText { get { return displayedText; } set { displayedText = value; modifiedTextSize = font.MeasureString(value); } }
|
||||
|
||||
/// <summary>
|
||||
/// The string to be displayed.
|
||||
/// </summary>
|
||||
public string Content { get { return originalText; } set { originalText = value; if (value == null) value = ellipsis; modifiedTextSize = font.MeasureString(value); displayedText = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a UI text object.
|
||||
/// </summary>
|
||||
/// <param name="font">The font to use.</param>
|
||||
/// <param name="content">The string for the text.</param>
|
||||
public Text(SpriteFont font, string content = null)
|
||||
{
|
||||
this.font = font ?? throw new ArgumentNullException("Font cannot be null.");
|
||||
Content = content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the positioning and attempts to perform any operations that were marked automatic.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">The game time.</param>
|
||||
public override void Update(GameTime gameTime)
|
||||
{
|
||||
position.X = X;
|
||||
position.Y = Y;
|
||||
|
||||
if (useEllipses) AttemptToApplyEllipsis();
|
||||
if (autoWrap) AttemptToWrapText();
|
||||
if (autoScale) AttemptToScaleFont();
|
||||
if (centered) Center();
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the text.
|
||||
/// </summary>
|
||||
/// <param name="batch">Batch to use.</param>
|
||||
public override void Draw(ConsistentSpriteBatch batch)
|
||||
{
|
||||
batch.DrawString(font, Content, position, color, 0f, default(Vector2), scale, SpriteEffects.None, 0f);
|
||||
base.Draw(batch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to apply ellipsis. Checks of nessecary.
|
||||
/// </summary>
|
||||
public void AttemptToApplyEllipsis()
|
||||
{
|
||||
if (modifiedTextSize.X * scale > Width && ModifiedText.Length > ellipsis.Length + 1)
|
||||
{
|
||||
RemoveLineBreaks();
|
||||
StringBuilder stringBuilder = new StringBuilder(ModifiedText);
|
||||
do
|
||||
{
|
||||
stringBuilder.Remove(stringBuilder.Length, ellipsis.Length - 1);
|
||||
stringBuilder.Insert(stringBuilder.Length, ellipsis);
|
||||
}
|
||||
while (font.MeasureString(stringBuilder).X * scale > Width);
|
||||
|
||||
ModifiedText = stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to scale the font. Checks if nessecary.
|
||||
/// </summary>
|
||||
public void AttemptToScaleFont()
|
||||
{
|
||||
|
||||
if (Width < Height)
|
||||
{
|
||||
if (Math.Round(modifiedTextSize.X * scale ) != Width)
|
||||
{
|
||||
scale = Width / modifiedTextSize.X;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Math.Round(modifiedTextSize.Y * scale ) != Height)
|
||||
{
|
||||
scale = Height / (modifiedTextSize.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes line breaks.
|
||||
/// </summary>
|
||||
public void RemoveLineBreaks()
|
||||
{
|
||||
ModifiedText = ModifiedText.Replace("\n", " ");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets to original text.
|
||||
/// </summary>
|
||||
public void ResetToOriginalText()
|
||||
{
|
||||
Content = originalText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to wrap text. Checks if nessecary.
|
||||
/// </summary>
|
||||
/// <param name="unwrap">If true, will first unwrap text, and the wrap again. This occurs before nessecity check.</param>
|
||||
public void AttemptToWrapText(bool unwrap = false)
|
||||
{
|
||||
if (unwrap) RemoveLineBreaks();
|
||||
if (modifiedTextSize.X * scale > Width)
|
||||
{
|
||||
ModifiedText = ModifiedText.Replace("\n", " ");
|
||||
string[] words = ModifiedText.Split(' ');
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
float currentScaledLineWidth = 0f;
|
||||
|
||||
for (int w = 0; w < words.Length; w++)
|
||||
{
|
||||
string word = words[w];
|
||||
float scaledWidth = font.MeasureString(word).X * scale;
|
||||
|
||||
if (currentScaledLineWidth + scaledWidth <= Width)
|
||||
{
|
||||
stringBuilder.Append(word);
|
||||
currentScaledLineWidth += scaledWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.AppendLine();
|
||||
currentScaledLineWidth = 0;
|
||||
}
|
||||
}
|
||||
ModifiedText = stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private bool Center()
|
||||
{
|
||||
Vector2 textSize = new Vector2(modifiedTextSize.X * scale, modifiedTextSize.Y * scale);
|
||||
|
||||
if (textSize.X <= Width)
|
||||
{
|
||||
position.X = X + (Width - textSize.X) / 2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (textSize.Y <= Height)
|
||||
{
|
||||
position.Y = Y + (Height - textSize.Y) / 2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
451
RecrownedAthenaeum/Graphics/UI/Modular/Modules/UIScrollable.cs
Normal file
451
RecrownedAthenaeum/Graphics/UI/Modular/Modules/UIScrollable.cs
Normal file
@@ -0,0 +1,451 @@
|
||||
using RecrownedAthenaeum.Input;
|
||||
using RecrownedAthenaeum.Graphics.Render;
|
||||
using RecrownedAthenaeum.Types;
|
||||
using RecrownedAthenaeum.Graphics.UI.SkinSystem;
|
||||
using RecrownedAthenaeum.Graphics.UI.SkinSystem.Definitions;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using System;
|
||||
|
||||
namespace RecrownedAthenaeum.Graphics.UI.Modular.Modules
|
||||
{
|
||||
public class UIScrollable : UIModule
|
||||
{
|
||||
BasicScissor basicScissor;
|
||||
Rectangle viewport;
|
||||
UIModuleGroup group;
|
||||
|
||||
Color4 scrollBarColor = Color4.White;
|
||||
float opacityOfBar = 1f;
|
||||
bool showingBars;
|
||||
private bool mouseWasPressed;
|
||||
private bool horizontalSelected;
|
||||
private Vector2 mouseRelativePosition;
|
||||
float shiftX, shiftY;
|
||||
|
||||
public float XScrollPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Width - horizontalScrollBarBounds.Width) * (-shiftX / (group.Width - viewport.Width));
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value > Width - verticalScrollBarBounds.Height)
|
||||
{
|
||||
value = Width - verticalScrollBarBounds.Height;
|
||||
}
|
||||
if (value < 0) value = 0;
|
||||
shiftX = -(group.Width - viewport.Width) * (value / (Width - horizontalScrollBarBounds.Width));
|
||||
WidthOrXChange(true);
|
||||
}
|
||||
}
|
||||
public float YScrollPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Height - verticalScrollBarBounds.Height) * (-shiftY / (group.Height - viewport.Height));
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value > Height - verticalScrollBarBounds.Height)
|
||||
{
|
||||
value = Height - verticalScrollBarBounds.Height;
|
||||
}
|
||||
if (value < 0) value = 0;
|
||||
shiftY = -(group.Height - viewport.Height) * (value / (Height - verticalScrollBarBounds.Height));
|
||||
HeightOrYChange(true);
|
||||
}
|
||||
}
|
||||
|
||||
UIModule furthestXModule, furthestYMod;
|
||||
|
||||
bool horScrollAvailable, vertScrollAvailable;
|
||||
|
||||
Rectangle horizontalScrollBarBounds, verticalScrollBarBounds;
|
||||
/// <summary>
|
||||
/// How fast the bars fade away in opacity (0 to 254) per second.
|
||||
/// </summary>
|
||||
public float barFadeSpeed = 250;
|
||||
|
||||
ISpecialDrawable horizontalScrollBar, verticalScrollBar;
|
||||
ISpecialDrawable background, horizontalBarTrack, verticalBarTrack;
|
||||
|
||||
private int topPadding, bottomPadding, leftPadding, rightPadding;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int PadTop { get { return topPadding; } set { topPadding = value; HeightOrYChange(); } }
|
||||
public int PadBottom { get { return bottomPadding; } set { bottomPadding = value; HeightOrYChange(); } }
|
||||
public int PadLeft { get { return leftPadding; } set { leftPadding = value; WidthOrXChange(); } }
|
||||
public int PadRight { get { return rightPadding; } set { rightPadding = value; WidthOrXChange(); } }
|
||||
|
||||
/// <summary>
|
||||
/// The minimum bar length for the scroll bar.
|
||||
/// </summary>
|
||||
public int minimumBarLength = 16;
|
||||
|
||||
public int HorizontalBarThickness { get { return horizontalScrollBarBounds.Height; } set { horizontalScrollBarBounds.Height = value; HeightOrYChange(); } }
|
||||
public int VerticalBarThickness { get { return verticalScrollBarBounds.Width; } set { verticalScrollBarBounds.Width = value; WidthOrXChange(); } }
|
||||
|
||||
bool hideScrollBars;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to hide scroll bars.
|
||||
/// </summary>
|
||||
public bool HideScrollBars
|
||||
{
|
||||
get { return hideScrollBars; }
|
||||
set
|
||||
{
|
||||
hideScrollBars = value;
|
||||
WidthOrXChange(true);
|
||||
HeightOrYChange(true);
|
||||
if (!value)
|
||||
{
|
||||
opacityOfBar = 1f;
|
||||
scrollBarColor = color.ReturnMultipliedByFloat(opacityOfBar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set to true to change from the normal position to the new position.
|
||||
/// </summary>
|
||||
public bool verticalBarLeftPosition, horizontalBarTopPosition;
|
||||
|
||||
|
||||
public override int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.Width = value;
|
||||
WidthOrXChange();
|
||||
}
|
||||
}
|
||||
|
||||
public override int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.Height = value;
|
||||
HeightOrYChange();
|
||||
}
|
||||
}
|
||||
|
||||
public override int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.X;
|
||||
}
|
||||
set
|
||||
{
|
||||
WidthOrXChange(true);
|
||||
base.X = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
HeightOrYChange(true);
|
||||
base.Y = value;
|
||||
}
|
||||
}
|
||||
|
||||
public UIScrollable(ISpecialDrawable horizontalScrollBar, ISpecialDrawable verticalScrollBar, ISpecialDrawable horizontalBarTrack = null, ISpecialDrawable verticalBarTrack = null, ISpecialDrawable background = null)
|
||||
{
|
||||
this.horizontalScrollBar = horizontalScrollBar;
|
||||
this.verticalScrollBar = verticalScrollBar;
|
||||
this.horizontalBarTrack = horizontalBarTrack;
|
||||
this.verticalBarTrack = verticalBarTrack;
|
||||
this.background = background;
|
||||
|
||||
basicScissor = new BasicScissor();
|
||||
group = new UIModuleGroup();
|
||||
HorizontalBarThickness = 12;
|
||||
VerticalBarThickness = 12;
|
||||
}
|
||||
|
||||
public UIScrollable(ISkin skin, string definition = null) :
|
||||
this(skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().horizontalBar, true),
|
||||
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().verticalBar, true),
|
||||
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().horizontalBarTrack),
|
||||
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().verticalBarTrack),
|
||||
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().background))
|
||||
{
|
||||
}
|
||||
|
||||
public override void Update(GameTime gameTime)
|
||||
{
|
||||
if (hideScrollBars)
|
||||
{
|
||||
if (!showingBars && !mouseWasPressed)
|
||||
{
|
||||
if (opacityOfBar > 0f)
|
||||
{
|
||||
opacityOfBar -= (barFadeSpeed / 255f) * (float)gameTime.ElapsedGameTime.TotalSeconds;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
opacityOfBar = 1f;
|
||||
}
|
||||
scrollBarColor = color.ReturnMultipliedByFloat(opacityOfBar);
|
||||
}
|
||||
|
||||
if (horScrollAvailable)
|
||||
{
|
||||
horizontalScrollBarBounds.X = (int)XScrollPosition;
|
||||
}
|
||||
|
||||
if (vertScrollAvailable)
|
||||
{
|
||||
verticalScrollBarBounds.Y = (int)YScrollPosition;
|
||||
}
|
||||
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
public override void Draw(ConsistentSpriteBatch spriteBatch)
|
||||
{
|
||||
background?.Draw(spriteBatch, Boundaries, color, origin: origin);
|
||||
spriteBatch.End();
|
||||
basicScissor.Begin(viewport, spriteBatch);
|
||||
group.Draw(spriteBatch);
|
||||
basicScissor.End();
|
||||
spriteBatch.Begin();
|
||||
if (horScrollAvailable)
|
||||
{
|
||||
horizontalScrollBar.Draw(spriteBatch, horizontalScrollBarBounds, scrollBarColor);
|
||||
}
|
||||
if (vertScrollAvailable)
|
||||
{
|
||||
horizontalScrollBar.Draw(spriteBatch, verticalScrollBarBounds, scrollBarColor);
|
||||
}
|
||||
base.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
public void AddModules(params UIModule[] addModules)
|
||||
{
|
||||
group.AddModules(addModules);
|
||||
|
||||
for (int i = 0; i < addModules.Length; i++)
|
||||
{
|
||||
UIModule m = addModules[i];
|
||||
int mFurthestX = m.Boundaries.X + m.Boundaries.Width;
|
||||
int mFurthestY = m.Boundaries.Y + m.Boundaries.Height;
|
||||
if (mFurthestX > group.Width)
|
||||
{
|
||||
furthestXModule = m;
|
||||
group.Width = mFurthestX;
|
||||
}
|
||||
if (mFurthestY > group.Height)
|
||||
{
|
||||
furthestYMod = m;
|
||||
group.Height = mFurthestY;
|
||||
}
|
||||
}
|
||||
|
||||
WidthOrXChange();
|
||||
HeightOrYChange();
|
||||
}
|
||||
|
||||
public void RemoveModule(UIModule module)
|
||||
{
|
||||
group.RemoveModule(module);
|
||||
|
||||
if (module == furthestXModule)
|
||||
{
|
||||
group.Width = 0;
|
||||
UIModule[] modules = group.GetCopyOfModules();
|
||||
for (int i = 0; i < modules.Length; i++)
|
||||
{
|
||||
UIModule m = modules[i];
|
||||
int mFurthestX = m.Boundaries.X + m.Boundaries.Width;
|
||||
if (mFurthestX > group.Width)
|
||||
{
|
||||
furthestXModule = m;
|
||||
group.Width = mFurthestX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (module == furthestYMod)
|
||||
{
|
||||
group.Height = 0;
|
||||
UIModule[] modules = group.GetCopyOfModules();
|
||||
|
||||
for (int i = 0; i < modules.Length; i++)
|
||||
{
|
||||
UIModule m = modules[i];
|
||||
int mFurthestY = m.Boundaries.Y + m.Boundaries.Height;
|
||||
if (mFurthestY > group.Height)
|
||||
{
|
||||
furthestYMod = m;
|
||||
group.Height = mFurthestY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WidthOrXChange(bool onlyXChange = false)
|
||||
{
|
||||
group.X = X + leftPadding + (int)shiftX;
|
||||
if (!onlyXChange)
|
||||
{
|
||||
viewport.X = X + leftPadding;
|
||||
viewport.Width = Width - rightPadding - leftPadding;
|
||||
if (Width < group.Width)
|
||||
{
|
||||
horScrollAvailable = true;
|
||||
horizontalScrollBarBounds.Width = (int)(Width * ((float)Width / group.Width));
|
||||
horizontalScrollBarBounds.Width = Math.Max(horizontalScrollBarBounds.Width, minimumBarLength);
|
||||
}
|
||||
else { horScrollAvailable = false; }
|
||||
|
||||
verticalScrollBarBounds.X = X;
|
||||
if (!hideScrollBars)
|
||||
{
|
||||
viewport.Width -= VerticalBarThickness;
|
||||
if (!verticalBarLeftPosition)
|
||||
{
|
||||
verticalScrollBarBounds.X += viewport.Width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!verticalBarLeftPosition)
|
||||
{
|
||||
verticalScrollBarBounds.X += viewport.Width - verticalScrollBarBounds.Width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HeightOrYChange(bool onlyYChange = false)
|
||||
{
|
||||
group.Y = Y + bottomPadding + (int)shiftY;
|
||||
if (!onlyYChange)
|
||||
{
|
||||
viewport.Y = Y + bottomPadding;
|
||||
viewport.Height = Height - bottomPadding - topPadding;
|
||||
if (Height < group.Height)
|
||||
{
|
||||
vertScrollAvailable = true;
|
||||
verticalScrollBarBounds.Height = (int)(Height * ((float)Height / group.Height));
|
||||
verticalScrollBarBounds.Height = Math.Max(verticalScrollBarBounds.Height, minimumBarLength);
|
||||
}
|
||||
else { vertScrollAvailable = false; }
|
||||
|
||||
horizontalScrollBarBounds.Y = Y;
|
||||
if (!hideScrollBars)
|
||||
{
|
||||
viewport.Height -= HorizontalBarThickness;
|
||||
if (!horizontalBarTopPosition)
|
||||
{
|
||||
horizontalScrollBarBounds.Y += viewport.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewport.Y += horizontalScrollBarBounds.Height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!horizontalBarTopPosition)
|
||||
{
|
||||
horizontalScrollBarBounds.Y += viewport.Height - horizontalScrollBarBounds.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool KeyboardStateChanged(KeyboardState state)
|
||||
{
|
||||
if (state.IsKeyDown(Keys.Right))
|
||||
{
|
||||
XScrollPosition += 1;
|
||||
}
|
||||
|
||||
return base.KeyboardStateChanged(state);
|
||||
}
|
||||
|
||||
public override bool MouseStateChanged(MouseState state)
|
||||
{
|
||||
if (InputUtilities.MouseWithinBoundries(Boundaries))
|
||||
{
|
||||
showingBars = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
showingBars = false;
|
||||
}
|
||||
|
||||
if (InputUtilities.MouseWithinBoundries(horizontalScrollBarBounds))
|
||||
{
|
||||
if (state.LeftButton == ButtonState.Pressed)
|
||||
{
|
||||
mouseWasPressed = true;
|
||||
horizontalSelected = true;
|
||||
}
|
||||
if (!mouseWasPressed)
|
||||
{
|
||||
mouseRelativePosition.X = state.X - horizontalScrollBarBounds.X;
|
||||
}
|
||||
}
|
||||
|
||||
if (InputUtilities.MouseWithinBoundries(verticalScrollBarBounds))
|
||||
{
|
||||
if (state.LeftButton == ButtonState.Pressed)
|
||||
{
|
||||
mouseWasPressed = true;
|
||||
horizontalSelected = false;
|
||||
}
|
||||
if (!mouseWasPressed)
|
||||
{
|
||||
mouseRelativePosition.Y = state.Y - verticalScrollBarBounds.Y;
|
||||
}
|
||||
}
|
||||
|
||||
if (mouseWasPressed)
|
||||
{
|
||||
if (horizontalSelected)
|
||||
{
|
||||
float latestPosition = state.X - mouseRelativePosition.X - X;
|
||||
XScrollPosition = latestPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
float latestPosition = state.Y - mouseRelativePosition.Y - Y;
|
||||
YScrollPosition = latestPosition;
|
||||
}
|
||||
|
||||
if (state.LeftButton == ButtonState.Released)
|
||||
{
|
||||
mouseWasPressed = false;
|
||||
}
|
||||
}
|
||||
return base.MouseStateChanged(state);
|
||||
}
|
||||
}
|
||||
}
|
190
RecrownedAthenaeum/Graphics/UI/Modular/UIModule.cs
Normal file
190
RecrownedAthenaeum/Graphics/UI/Modular/UIModule.cs
Normal file
@@ -0,0 +1,190 @@
|
||||
using RecrownedAthenaeum.Types;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using RecrownedAthenaeum.Input;
|
||||
using RecrownedAthenaeum.Graphics.Render;
|
||||
using System;
|
||||
|
||||
namespace RecrownedAthenaeum.Graphics.UI.Modular
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Module for UI layout.
|
||||
/// </summary>
|
||||
public abstract class UIModule : IInputListener
|
||||
{
|
||||
/// <summary>
|
||||
/// The width of the module.
|
||||
/// </summary>
|
||||
public virtual int Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The height of the module.
|
||||
/// </summary>
|
||||
public virtual int Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The X position of the module.
|
||||
/// </summary>
|
||||
public virtual int X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Y position of the module.
|
||||
/// </summary>
|
||||
public virtual int Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Bounds of this module (after factoring in the origin).
|
||||
/// </summary>
|
||||
public Rectangle Boundaries
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Rectangle((int)(X - origin.X), (int)(Y - origin.Y), Width, Height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Origin of this module.
|
||||
/// </summary>
|
||||
public Vector2 origin;
|
||||
|
||||
/// <summary>
|
||||
/// The parent of this module. May be null.
|
||||
/// </summary>
|
||||
public UIModuleGroup parent;
|
||||
|
||||
/// <summary>
|
||||
/// Name of this module. For organizational/referencial purposes mostly.
|
||||
/// </summary>
|
||||
public string name;
|
||||
|
||||
/// <summary>
|
||||
/// The color tint of this module.
|
||||
/// </summary>
|
||||
public Color4 color = Color4.White;
|
||||
|
||||
/// <summary>
|
||||
/// Called every frame to update this module. Calculations and movement should go here.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">Game time information.</param>
|
||||
public virtual void Update(GameTime gameTime)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called every frame to draw this module. Anything that needs to be drawn should go here.
|
||||
/// </summary>
|
||||
/// <param name="batch">Batch used to draw.</param>
|
||||
public virtual void Draw(ConsistentSpriteBatch batch)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given rectangle to the coordinates of the parent.
|
||||
/// </summary>
|
||||
/// <param name="rectangle">Rectangle to convert.</param>
|
||||
/// <returns></returns>
|
||||
public Rectangle ConvertToParentCoordinates(Rectangle rectangle)
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
Rectangle parentHitbox = parent.ConvertToParentCoordinates(rectangle);
|
||||
int tX = rectangle.X + parentHitbox.X;
|
||||
int tY = rectangle.Y + parentHitbox.Y;
|
||||
return new Rectangle(tX, tY, rectangle.Width, rectangle.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
return rectangle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes this module from the parent.
|
||||
/// </summary>
|
||||
public void RemoveFromParent()
|
||||
{
|
||||
if (parent == null) throw new InvalidOperationException("Parent is null.");
|
||||
parent.RemoveModule(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever the keyboard state is changed.
|
||||
/// </summary>
|
||||
/// <param name="state">The current keyboard state.</param>
|
||||
/// <returns>Returning whether or not to continue to call the next listener.</returns>
|
||||
public virtual bool KeyboardStateChanged(KeyboardState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever the state of the mouse changes. This includes movement.
|
||||
/// </summary>
|
||||
/// <param name="state">The current state of the mouse.</param>
|
||||
/// <returns>Returning whether or not to continue to call the next listener.</returns>
|
||||
public virtual bool MouseStateChanged(MouseState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the origin to be the center using the <see cref="Width"/> and <see cref="Height"/>.
|
||||
/// </summary>
|
||||
public virtual void CenterOrigin()
|
||||
{
|
||||
origin.X = Width / 2f;
|
||||
origin.Y = Height / 2f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Centers this module's on the horizontal axis relative to the parent <see cref="UIModuleGroup"/>.
|
||||
/// </summary>
|
||||
/// <returns>True if possible and false if not.</returns>
|
||||
public bool CenterHorizontally()
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
Rectangle rectangle = parent.Boundaries;
|
||||
if (parent != null && rectangle.Width >= Boundaries.Width)
|
||||
{
|
||||
X = rectangle.Width / 2 + X;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Centers this module's origin on the vertical axis relative to the parent <see cref="UIModuleGroup"/>.
|
||||
/// </summary>
|
||||
/// <returns>True if possible.</returns>
|
||||
public virtual bool CenterVertically()
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
Rectangle rectangle = parent.Boundaries;
|
||||
if (rectangle.Height >= Boundaries.Height)
|
||||
{
|
||||
Y = rectangle.Height / 2 + Y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position and dimension of this module.
|
||||
/// </summary>
|
||||
/// <param name="rectangle">The rectangle that represents the position and dimensions of the module.</param>
|
||||
public virtual void SetPositionAndDimensions(Rectangle rectangle)
|
||||
{
|
||||
X = rectangle.X;
|
||||
Y = rectangle.Y;
|
||||
Width = rectangle.Width;
|
||||
Height = rectangle.Height;
|
||||
}
|
||||
}
|
||||
}
|
136
RecrownedAthenaeum/Graphics/UI/Modular/UIModuleGroup.cs
Normal file
136
RecrownedAthenaeum/Graphics/UI/Modular/UIModuleGroup.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using RecrownedAthenaeum.Graphics.Render;
|
||||
|
||||
namespace RecrownedAthenaeum.Graphics.UI.Modular
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Contains a group of modules and has its own relative coordinate system.
|
||||
/// </summary>
|
||||
public class UIModuleGroup : UIModule
|
||||
{
|
||||
List<UIModule> modules = new List<UIModule>();
|
||||
|
||||
/// <summary>
|
||||
/// Set this to crop anything that flows out of the boundaries of this group. Will not crop if this is null.
|
||||
/// </summary>
|
||||
public BasicScissor basicScissor;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates the UI module group.
|
||||
/// </summary>
|
||||
/// <param name="basicScissor">Sets the <see cref="basicScissor"/> field.</param>
|
||||
public UIModuleGroup(BasicScissor basicScissor = null)
|
||||
{
|
||||
this.basicScissor = basicScissor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws this group of modules. If scissoring, will use the matrix and effect designated in the <see cref="BasicScissor"/> to begin the batch normally again.
|
||||
/// </summary>
|
||||
/// <param name="spriteBatch">Batch used to draw the group.</param>
|
||||
public override void Draw(ConsistentSpriteBatch spriteBatch)
|
||||
{
|
||||
if (basicScissor != null)
|
||||
{
|
||||
spriteBatch.End();
|
||||
basicScissor.Begin(Boundaries, spriteBatch);
|
||||
}
|
||||
|
||||
foreach (UIModule module in modules)
|
||||
{
|
||||
int offsetX = module.X;
|
||||
int offsetY = module.Y;
|
||||
module.X = X + offsetX;
|
||||
module.Y = Y + offsetY;
|
||||
module.Draw(spriteBatch);
|
||||
module.X = offsetX;
|
||||
module.Y = offsetY;
|
||||
}
|
||||
|
||||
if (basicScissor != null)
|
||||
{
|
||||
basicScissor.End();
|
||||
spriteBatch.Begin();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the group of modules.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">Game time used.</param>
|
||||
public override void Update(GameTime gameTime)
|
||||
{
|
||||
foreach (UIModule module in modules)
|
||||
{
|
||||
module.Update(gameTime);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds module(s) to this group.
|
||||
/// </summary>
|
||||
/// <param name="addModules">The module(s) to add.</param>
|
||||
public virtual void AddModules(params UIModule[] addModules)
|
||||
{
|
||||
foreach (UIModule module in addModules)
|
||||
{
|
||||
if (modules.Contains(module))
|
||||
{
|
||||
throw new InvalidOperationException(module.ToString() + " already exists in " + this.ToString());
|
||||
}
|
||||
module.parent = this;
|
||||
modules.Add(module);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes given module from group.
|
||||
/// </summary>
|
||||
/// <param name="module">module to remove.</param>
|
||||
public virtual void RemoveModule(UIModule module)
|
||||
{
|
||||
module.parent = null;
|
||||
modules.Remove(module);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains an array snapshot of all the modules.
|
||||
/// </summary>
|
||||
public UIModule[] GetCopyOfModules()
|
||||
{
|
||||
return modules.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the keyboard state of the modules in this group.
|
||||
/// </summary>
|
||||
/// <param name="state">The new state.</param>
|
||||
/// <returns>Whether or not to continue updating the other listeners.</returns>
|
||||
public override bool KeyboardStateChanged(KeyboardState state)
|
||||
{
|
||||
foreach (UIModule module in modules)
|
||||
{
|
||||
module.KeyboardStateChanged(state);
|
||||
}
|
||||
return base.KeyboardStateChanged(state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the moues state of the modules in this group.
|
||||
/// </summary>
|
||||
/// <param name="state">The new state.</param>
|
||||
/// <returns>Whether or not to continue updating other listeners.</returns>
|
||||
public override bool MouseStateChanged(MouseState state)
|
||||
{
|
||||
foreach (UIModule module in modules)
|
||||
{
|
||||
module.MouseStateChanged(state);
|
||||
}
|
||||
return base.MouseStateChanged(state);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user