218 lines
7.0 KiB
C#
218 lines
7.0 KiB
C#
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using System;
|
|
using System.Text;
|
|
using System.Xml.Linq;
|
|
|
|
namespace Barotrauma.Items.Components
|
|
{
|
|
partial class ItemLabel : ItemComponent, IDrawableComponent
|
|
{
|
|
private GUITextBlock textBlock;
|
|
|
|
private Color textColor;
|
|
|
|
private float scrollAmount;
|
|
private string scrollingText;
|
|
private float scrollPadding;
|
|
private int scrollIndex;
|
|
private bool needsScrolling;
|
|
|
|
private float[] charWidths;
|
|
|
|
[Serialize("0,0,0,0", true)]
|
|
public Vector4 Padding
|
|
{
|
|
get { return TextBlock.Padding; }
|
|
set { TextBlock.Padding = value; }
|
|
}
|
|
|
|
private string text;
|
|
[Serialize("", true), Editable(100)]
|
|
public string Text
|
|
{
|
|
get { return text; }
|
|
set
|
|
{
|
|
if (value == text || item.Rect.Width < 5) return;
|
|
|
|
if (TextBlock.Rect.Width != item.Rect.Width || textBlock.Rect.Height != item.Rect.Height)
|
|
{
|
|
textBlock = null;
|
|
}
|
|
|
|
text = value;
|
|
TextBlock.Text = value;
|
|
SetScrollingText();
|
|
}
|
|
}
|
|
|
|
[Editable, Serialize("0.0,0.0,0.0,1.0", true)]
|
|
public Color TextColor
|
|
{
|
|
get { return textColor; }
|
|
set
|
|
{
|
|
if (textBlock != null) textBlock.TextColor = value;
|
|
textColor = value;
|
|
}
|
|
}
|
|
|
|
[Editable(0.0f, 10.0f), Serialize(1.0f, true)]
|
|
public float TextScale
|
|
{
|
|
get { return textBlock == null ? 1.0f : textBlock.TextScale; }
|
|
set
|
|
{
|
|
if (textBlock != null) textBlock.TextScale = MathHelper.Clamp(value, 0.1f, 10.0f);
|
|
}
|
|
}
|
|
|
|
private bool scrollable;
|
|
[Serialize(false, true)]
|
|
public bool Scrollable
|
|
{
|
|
get { return scrollable; }
|
|
set
|
|
{
|
|
scrollable = value;
|
|
IsActive = value;
|
|
TextBlock.Wrap = !scrollable;
|
|
TextBlock.TextAlignment = scrollable ? Alignment.CenterLeft : Alignment.Center;
|
|
}
|
|
}
|
|
|
|
[Serialize(20.0f, true)]
|
|
public float ScrollSpeed
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
private GUITextBlock TextBlock
|
|
{
|
|
get
|
|
{
|
|
if (textBlock == null)
|
|
{
|
|
textBlock = new GUITextBlock(new RectTransform(item.Rect.Size), "",
|
|
textColor: textColor, font: GUI.SmallFont, textAlignment: Alignment.Center, wrap: true, style: null)
|
|
{
|
|
TextDepth = item.SpriteDepth - 0.0001f,
|
|
TextScale = TextScale
|
|
};
|
|
}
|
|
return textBlock;
|
|
}
|
|
}
|
|
|
|
public ItemLabel(Item item, XElement element)
|
|
: base(item, element)
|
|
{
|
|
}
|
|
|
|
private void SetScrollingText()
|
|
{
|
|
if (!scrollable) return;
|
|
|
|
float totalWidth = textBlock.Font.MeasureString(text).X;
|
|
float textAreaWidth = Math.Max(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z, 0);
|
|
if (totalWidth >= textAreaWidth)
|
|
{
|
|
//add enough spaces to fill the rect
|
|
//(so the text can scroll entirely out of view before we reset it back to start)
|
|
needsScrolling = true;
|
|
float spaceWidth = textBlock.Font.MeasureChar(' ').X;
|
|
scrollingText = new string(' ', (int)Math.Ceiling(textAreaWidth / spaceWidth)) + text;
|
|
}
|
|
else
|
|
{
|
|
//whole text can fit in the textblock, no need to scroll
|
|
needsScrolling = false;
|
|
scrollingText = text;
|
|
scrollAmount = 0.0f;
|
|
scrollIndex = 0;
|
|
return;
|
|
}
|
|
|
|
//calculate character widths
|
|
scrollPadding = 0;
|
|
charWidths = new float[scrollingText.Length];
|
|
for (int i = 0; i < scrollingText.Length; i++)
|
|
{
|
|
float charWidth = TextBlock.Font.MeasureChar(scrollingText[i]).X;
|
|
scrollPadding = Math.Max(charWidth, scrollPadding);
|
|
charWidths[i] = charWidth;
|
|
}
|
|
|
|
scrollIndex = MathHelper.Clamp(scrollIndex, 0, text.Length);
|
|
}
|
|
|
|
public override void Update(float deltaTime, Camera cam)
|
|
{
|
|
if (!scrollable) return;
|
|
|
|
if (scrollingText == null)
|
|
{
|
|
SetScrollingText();
|
|
}
|
|
|
|
if (!needsScrolling) return;
|
|
|
|
scrollAmount -= deltaTime * ScrollSpeed;
|
|
|
|
float currLength = 0;
|
|
StringBuilder sb = new StringBuilder();
|
|
float textAreaWidth = textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z;
|
|
for (int i = scrollIndex; i < scrollingText.Length; i++)
|
|
{
|
|
//first character is out of view -> skip to next character
|
|
if (i == scrollIndex && scrollAmount < -charWidths[i])
|
|
{
|
|
scrollIndex++;
|
|
scrollAmount = 0;
|
|
if (scrollIndex >= scrollingText.Length) //reached the last character, reset
|
|
{
|
|
scrollIndex = 0;
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
//reached the right edge, stop adding more character
|
|
if (scrollAmount + (currLength + charWidths[i] + scrollPadding) >= textAreaWidth)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
currLength += charWidths[i];
|
|
sb.Append(scrollingText[i]);
|
|
}
|
|
}
|
|
|
|
TextBlock.Text = sb.ToString();
|
|
}
|
|
|
|
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
|
{
|
|
var drawPos = new Vector2(
|
|
item.DrawPosition.X - item.Rect.Width / 2.0f,
|
|
-(item.DrawPosition.Y + item.Rect.Height / 2.0f));
|
|
|
|
Rectangle worldRect = item.WorldRect;
|
|
if (worldRect.X > Screen.Selected.Cam.WorldView.Right ||
|
|
worldRect.Right < Screen.Selected.Cam.WorldView.X ||
|
|
worldRect.Y < Screen.Selected.Cam.WorldView.Y - Screen.Selected.Cam.WorldView.Height ||
|
|
worldRect.Y - worldRect.Height > Screen.Selected.Cam.WorldView.Y)
|
|
{
|
|
return;
|
|
}
|
|
|
|
textBlock.TextDepth = item.SpriteDepth - 0.0001f;
|
|
textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + new Vector2(scrollAmount + scrollPadding, 0.0f);
|
|
textBlock.DrawManually(spriteBatch);
|
|
}
|
|
}
|
|
}
|