2 using Microsoft.Xna.Framework;
3 using Microsoft.Xna.Framework.Graphics;
5 using System.Collections.Generic;
12 partial class ItemLabel : ItemComponent, IDrawableComponent, IHasExtraTextPickerEntries
14 private GUITextBlock textBlock;
16 private Color textColor;
18 private float scrollAmount;
19 private string scrollingText;
20 private float scrollPadding;
21 private int scrollIndex;
22 private bool needsScrolling;
24 private float[] charWidths;
26 private float prevScale;
28 private StringBuilder sb;
30 private Vector4 padding;
32 [Serialize(
"0,0,0,0",
IsPropertySaveable.Yes, description:
"The amount of padding around the text in pixels (left,top,right,bottom).")]
35 get {
return padding; }
50 if (value == text ||
item.
Rect.Width < 5) {
return; }
58 SetDisplayText(value);
59 UpdateScrollingText();
63 private bool ignoreLocalization;
68 get => ignoreLocalization;
71 ignoreLocalization = value;
82 [
Editable,
Serialize(
"0,0,0,255",
IsPropertySaveable.Yes, description:
"The color of the text displayed on the label (R,G,B,A).", alwaysUseInstanceValues:
true)]
85 get {
return textColor; }
88 if (textBlock !=
null) { textBlock.TextColor = value; }
96 get {
return textBlock ==
null ? 1.0f : textBlock.TextScale / BaseToRealTextScaleFactor; }
99 if (textBlock !=
null)
102 textBlock.TextScale = MathHelper.Clamp(value * BaseToRealTextScaleFactor, 0.1f, 10.0f);
103 if (!MathUtils.NearlyEqual(prevScale, TextBlock.
TextScale))
111 private bool scrollable;
112 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Should the text scroll horizontally across the item if it's too long to be displayed all at once.")]
115 get {
return scrollable; }
119 IsActive = value || parseSpecialTextTagOnStart;
120 TextBlock.
Wrap = !scrollable;
121 TextBlock.
TextAlignment = scrollable ? Alignment.CenterLeft : Alignment.Center;
125 [
Serialize(20.0f,
IsPropertySaveable.Yes, description:
"How fast the text scrolls across the item (only valid if Scrollable is set to true).")]
136 if (textBlock ==
null)
145 : base(
item, element)
151 return SpecialTextTags;
154 private void SetScrollingText()
156 if (!scrollable) {
return; }
159 float textAreaWidth = Math.Max(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z, 0);
160 if (totalWidth >= textAreaWidth)
164 needsScrolling =
true;
165 float spaceWidth = textBlock.Font.MeasureChar(
' ').X * TextBlock.
TextScale;
166 scrollingText =
new string(
' ', (
int)Math.Ceiling(textAreaWidth / spaceWidth)) +
DisplayText.
Value;
171 needsScrolling =
false;
181 charWidths =
new float[scrollingText.Length];
182 for (
int i = 0; i < scrollingText.Length; i++)
185 scrollPadding = Math.Max(charWidth, scrollPadding);
186 charWidths[i] = charWidth;
192 private static readonly
string[] SpecialTextTags =
new string[] {
"[CurrentLocationName]",
"[CurrentBiomeName]",
"[CurrentSubName]" };
193 private bool parseSpecialTextTagOnStart;
194 private void SetDisplayText(
string value)
196 if (SpecialTextTags.Contains(value))
198 parseSpecialTextTagOnStart =
true;
205 if (Screen.Selected == GameMain.SubEditorScreen &&
Scrollable)
213 private const float BaseTextSize = 12.0f;
214 private float BaseToRealTextScaleFactor => BaseTextSize / GUIStyle.UnscaledSmallFont.Size;
215 private void RecreateTextBlock()
217 textBlock =
new GUITextBlock(
new RectTransform(
item.
Rect.Size),
"",
218 textColor: textColor, font: GUIStyle.UnscaledSmallFont, textAlignment: scrollable ? Alignment.CenterLeft : Alignment.Center, wrap: !scrollable, style:
null)
221 RoundToNearestPixel =
false,
227 private void ParseSpecialTextTag()
231 case "[CurrentLocationName]":
232 SetDisplayText(Level.Loaded?.StartLocation?.DisplayName.Value ??
string.Empty);
234 case "[CurrentBiomeName]":
235 SetDisplayText(Level.Loaded?.LevelData?.Biome?.DisplayName.Value ??
string.Empty);
237 case "[CurrentSubName]":
247 if (parseSpecialTextTagOnStart)
249 ParseSpecialTextTag();
250 parseSpecialTextTagOnStart =
false;
259 if (scrollingText ==
null)
264 if (!needsScrolling) {
return; }
267 UpdateScrollingText();
270 private void UpdateScrollingText()
272 if (!scrollable || !needsScrolling) {
return; }
274 float currLength = 0;
275 sb ??=
new StringBuilder();
277 float textAreaWidth = textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z;
278 for (
int i = scrollIndex; i < scrollingText.Length; i++)
281 if (i == scrollIndex && scrollAmount < -charWidths[i])
285 if (scrollIndex >= scrollingText.Length)
294 if (scrollAmount + (currLength + charWidths[i] + scrollPadding) >= textAreaWidth)
300 currLength += charWidths[i];
301 sb.Append(scrollingText[i]);
311 SetDisplayText(
Text);
316 public void Draw(SpriteBatch spriteBatch,
bool editing =
false,
float itemDepth = -1, Color? overrideColor =
null)
324 SetDisplayText(
Text);
330 var drawPos =
new Vector2(
335 textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + (editing ? Vector2.Zero :
new Vector2(scrollAmount + scrollPadding, 0.0f));
336 textBlock.DrawManually(spriteBatch);
virtual Vector2 DrawPosition
Vector2 MeasureChar(char c)
Inventory ParentInventory
void Draw(SpriteBatch spriteBatch, bool editing=false, float itemDepth=-1, Color? overrideColor=null)
void ClientEventRead(IReadMessage msg, float sendingTime)
IEnumerable< string > GetExtraTextPickerEntries()
LocalizedString DisplayText
override void OnScaleChanged()
ItemLabel(Item item, ContentXElement element)
override void Update(float deltaTime, Camera cam)
override string ToString()
LocalizedString DisplayName