recrownedathenaeum/RecrownedAthenaeum/UI/Modular/Modules/UIScrollable.cs

456 lines
15 KiB
C#
Raw Normal View History

2019-04-09 04:58:27 +00:00
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using RecrownedAthenaeum.Input;
using RecrownedAthenaeum.Render;
using RecrownedAthenaeum.SpecialTypes;
using RecrownedAthenaeum.UI.SkinSystem;
using RecrownedAthenaeum.UI.SkinSystem.Definitions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RecrownedAthenaeum.UI.Modular.Modules
{
public class UIScrollable : UIModule
{
2019-04-28 04:22:33 +00:00
BasicScissor basicScissor;
Rectangle viewport;
2019-04-09 04:58:27 +00:00
UIModuleGroup group;
2019-05-30 03:19:17 +00:00
Color scrollBarColor = Color.White;
float opacityOfBar = 1f;
2019-04-09 04:58:27 +00:00
bool showingBars;
private bool mouseWasPressed;
private bool horizontalSelected;
private Vector2 mouseRelativePosition;
float shiftX, shiftY;
2019-04-28 04:22:33 +00:00
public float XScrollPosition
{
get
{
return (Width - horizontalScrollBarBounds.Width) * (-shiftX / (group.Width - viewport.Width));
2019-04-28 04:22:33 +00:00
}
set
{
if (value > Width - verticalScrollBarBounds.Height)
{
value = Width - verticalScrollBarBounds.Height;
}
if (value < 0) value = 0;
shiftX = -(group.Width - viewport.Width) * (value / (Width - horizontalScrollBarBounds.Width));
2019-04-28 04:22:33 +00:00
WidthOrXChange(true);
}
}
public float YScrollPosition
{
get
{
return (Height - verticalScrollBarBounds.Height) * (-shiftY / (group.Height - viewport.Height));
2019-04-28 04:22:33 +00:00
}
set
{
if (value > Height - verticalScrollBarBounds.Height)
{
value = Height - verticalScrollBarBounds.Height;
}
if (value < 0) value = 0;
2019-05-30 03:19:17 +00:00
shiftY = -(group.Height - viewport.Height) * (value / (Height - verticalScrollBarBounds.Height));
2019-04-28 04:22:33 +00:00
HeightOrYChange(true);
}
}
UIModule furthestXModule, furthestYMod;
2019-04-09 04:58:27 +00:00
bool horScrollAvailable, vertScrollAvailable;
Rectangle horizontalScrollBarBounds, verticalScrollBarBounds;
/// <summary>
/// How fast the bars fade away in opacity (0 to 254) per second.
/// </summary>
2019-04-16 01:25:36 +00:00
public float barFadeSpeed = 250;
2019-04-09 04:58:27 +00:00
ISpecialDrawable horizontalScrollBar, verticalScrollBar;
ISpecialDrawable background, horizontalBarTrack, verticalBarTrack;
private int topPadding, bottomPadding, leftPadding, rightPadding;
2019-05-30 03:19:17 +00:00
/// <summary>
///
/// </summary>
2019-04-09 04:58:27 +00:00
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;
2019-04-13 02:46:12 +00:00
public int HorizontalBarThickness { get { return horizontalScrollBarBounds.Height; } set { horizontalScrollBarBounds.Height = value; HeightOrYChange(); } }
public int VerticalBarThickness { get { return verticalScrollBarBounds.Width; } set { verticalScrollBarBounds.Width = value; WidthOrXChange(); } }
2019-04-09 04:58:27 +00:00
2019-05-30 03:19:17 +00:00
bool hideScrollBars;
2019-04-09 04:58:27 +00:00
/// <summary>
/// Whether or not to hide scroll bars.
/// </summary>
public bool HideScrollBars
{
get { return hideScrollBars; }
set
{
hideScrollBars = value;
2019-04-16 01:25:36 +00:00
WidthOrXChange(true);
HeightOrYChange(true);
if (!value)
{
opacityOfBar = 1f;
2019-05-30 03:19:17 +00:00
scrollBarColor = color * opacityOfBar;
2019-04-16 01:25:36 +00:00
}
2019-04-09 04:58:27 +00:00
}
}
/// <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;
2019-04-28 04:22:33 +00:00
basicScissor = new BasicScissor();
group = new UIModuleGroup();
2019-04-13 02:46:12 +00:00
HorizontalBarThickness = 12;
VerticalBarThickness = 12;
2019-04-09 04:58:27 +00:00
}
2019-04-13 02:46:12 +00:00
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),
2019-04-09 04:58:27 +00:00
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().background))
{
}
public override void Update(GameTime gameTime)
{
if (hideScrollBars)
{
if (!showingBars && !mouseWasPressed)
2019-04-09 04:58:27 +00:00
{
2019-04-16 01:25:36 +00:00
if (opacityOfBar > 0f)
2019-04-09 04:58:27 +00:00
{
2019-04-16 01:25:36 +00:00
opacityOfBar -= (barFadeSpeed / 255f) * (float)gameTime.ElapsedGameTime.TotalSeconds;
2019-04-09 04:58:27 +00:00
}
}
else
{
opacityOfBar = 1f;
}
2019-05-30 03:19:17 +00:00
scrollBarColor = color * opacityOfBar;
2019-04-09 04:58:27 +00:00
}
if (horScrollAvailable)
{
horizontalScrollBarBounds.X = (int)XScrollPosition;
2019-04-09 04:58:27 +00:00
}
if (vertScrollAvailable)
{
verticalScrollBarBounds.Y = (int)YScrollPosition;
2019-04-09 04:58:27 +00:00
}
2019-04-28 04:22:33 +00:00
2019-04-09 04:58:27 +00:00
base.Update(gameTime);
}
public override void Draw(ConsistentSpriteBatch spriteBatch)
{
2019-04-11 05:51:26 +00:00
background?.Draw(spriteBatch, Boundaries, color, origin: origin);
2019-04-28 04:22:33 +00:00
spriteBatch.End();
basicScissor.Begin(viewport, spriteBatch);
2019-04-11 05:51:26 +00:00
group.Draw(spriteBatch);
2019-04-28 04:22:33 +00:00
basicScissor.End();
spriteBatch.Begin();
2019-04-09 04:58:27 +00:00
if (horScrollAvailable)
{
2019-04-16 01:25:36 +00:00
horizontalScrollBar.Draw(spriteBatch, horizontalScrollBarBounds, scrollBarColor);
2019-04-09 04:58:27 +00:00
}
if (vertScrollAvailable)
{
2019-04-16 01:25:36 +00:00
horizontalScrollBar.Draw(spriteBatch, verticalScrollBarBounds, scrollBarColor);
2019-04-09 04:58:27 +00:00
}
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;
2019-04-28 04:22:33 +00:00
if (mFurthestX > group.Width)
2019-04-09 04:58:27 +00:00
{
furthestXModule = m;
2019-04-28 04:22:33 +00:00
group.Width = mFurthestX;
2019-04-09 04:58:27 +00:00
}
2019-04-28 04:22:33 +00:00
if (mFurthestY > group.Height)
2019-04-09 04:58:27 +00:00
{
furthestYMod = m;
2019-04-28 04:22:33 +00:00
group.Height = mFurthestY;
2019-04-09 04:58:27 +00:00
}
}
2019-04-11 05:51:26 +00:00
WidthOrXChange();
HeightOrYChange();
2019-04-09 04:58:27 +00:00
}
public void RemoveModule(UIModule module)
{
group.RemoveModule(module);
if (module == furthestXModule)
2019-04-09 04:58:27 +00:00
{
2019-04-28 04:22:33 +00:00
group.Width = 0;
2019-04-09 04:58:27 +00:00
UIModule[] modules = group.GetCopyOfModules();
for (int i = 0; i < modules.Length; i++)
{
UIModule m = modules[i];
int mFurthestX = m.Boundaries.X + m.Boundaries.Width;
2019-04-28 04:22:33 +00:00
if (mFurthestX > group.Width)
2019-04-09 04:58:27 +00:00
{
furthestXModule = m;
2019-04-28 04:22:33 +00:00
group.Width = mFurthestX;
2019-04-09 04:58:27 +00:00
}
}
}
if (module == furthestYMod)
{
2019-04-28 04:22:33 +00:00
group.Height = 0;
2019-04-09 04:58:27 +00:00
UIModule[] modules = group.GetCopyOfModules();
for (int i = 0; i < modules.Length; i++)
{
UIModule m = modules[i];
int mFurthestY = m.Boundaries.Y + m.Boundaries.Height;
2019-04-28 04:22:33 +00:00
if (mFurthestY > group.Height)
2019-04-09 04:58:27 +00:00
{
furthestYMod = m;
2019-04-28 04:22:33 +00:00
group.Height = mFurthestY;
2019-04-09 04:58:27 +00:00
}
}
}
}
private void WidthOrXChange(bool onlyXChange = false)
{
2019-04-28 04:22:33 +00:00
group.X = X + leftPadding + (int)shiftX;
2019-04-09 04:58:27 +00:00
if (!onlyXChange)
{
2019-04-28 04:22:33 +00:00
viewport.X = X + leftPadding;
viewport.Width = Width - rightPadding - leftPadding;
if (Width < group.Width)
2019-04-09 04:58:27 +00:00
{
horScrollAvailable = true;
2019-04-28 04:22:33 +00:00
horizontalScrollBarBounds.Width = (int)(Width * ((float)Width / group.Width));
2019-04-09 04:58:27 +00:00
horizontalScrollBarBounds.Width = Math.Max(horizontalScrollBarBounds.Width, minimumBarLength);
}
else { horScrollAvailable = false; }
2019-04-16 01:25:36 +00:00
verticalScrollBarBounds.X = X;
2019-04-09 04:58:27 +00:00
if (!hideScrollBars)
{
2019-04-28 04:22:33 +00:00
viewport.Width -= VerticalBarThickness;
2019-04-13 02:46:12 +00:00
if (!verticalBarLeftPosition)
2019-04-09 04:58:27 +00:00
{
2019-04-28 04:22:33 +00:00
verticalScrollBarBounds.X += viewport.Width;
2019-04-09 04:58:27 +00:00
}
2019-04-16 01:25:36 +00:00
}
else
{
if (!verticalBarLeftPosition)
{
2019-04-28 04:22:33 +00:00
verticalScrollBarBounds.X += viewport.Width - verticalScrollBarBounds.Width;
2019-04-16 01:25:36 +00:00
}
2019-04-09 04:58:27 +00:00
}
}
}
private void HeightOrYChange(bool onlyYChange = false)
{
2019-04-28 04:22:33 +00:00
group.Y = Y + bottomPadding + (int)shiftY;
2019-04-09 04:58:27 +00:00
if (!onlyYChange)
{
2019-04-28 04:22:33 +00:00
viewport.Y = Y + bottomPadding;
viewport.Height = Height - bottomPadding - topPadding;
if (Height < group.Height)
2019-04-09 04:58:27 +00:00
{
2019-04-11 05:51:26 +00:00
vertScrollAvailable = true;
2019-04-28 04:22:33 +00:00
verticalScrollBarBounds.Height = (int)(Height * ((float)Height / group.Height));
2019-04-09 04:58:27 +00:00
verticalScrollBarBounds.Height = Math.Max(verticalScrollBarBounds.Height, minimumBarLength);
}
else { vertScrollAvailable = false; }
2019-04-16 01:25:36 +00:00
horizontalScrollBarBounds.Y = Y;
2019-04-09 04:58:27 +00:00
if (!hideScrollBars)
{
2019-04-28 04:22:33 +00:00
viewport.Height -= HorizontalBarThickness;
2019-04-09 04:58:27 +00:00
if (!horizontalBarTopPosition)
{
2019-04-28 04:22:33 +00:00
horizontalScrollBarBounds.Y += viewport.Height;
2019-04-13 02:46:12 +00:00
}
else
{
2019-04-28 04:22:33 +00:00
viewport.Y += horizontalScrollBarBounds.Height;
2019-04-09 04:58:27 +00:00
}
}
2019-04-16 01:25:36 +00:00
else
{
if (!horizontalBarTopPosition)
{
2019-04-28 04:22:33 +00:00
horizontalScrollBarBounds.Y += viewport.Height - horizontalScrollBarBounds.Height;
2019-04-16 01:25:36 +00:00
}
}
2019-04-09 04:58:27 +00:00
}
}
public override bool KeyboardStateChanged(KeyboardState state)
{
if (state.IsKeyDown(Keys.Right))
{
XScrollPosition += 1;
}
return base.KeyboardStateChanged(state);
}
2019-04-09 04:58:27 +00:00
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;
}
}
2019-04-09 04:58:27 +00:00
return base.MouseStateChanged(state);
}
}
}