3 using System.Collections.Generic;
5 using System.Text.RegularExpressions;
6 using Microsoft.Xna.Framework;
7 using Microsoft.Xna.Framework.Graphics;
26 public readonly
string Text;
27 public readonly Vector2
Size;
38 : tagTypes.HasFlag(
TagType.Bold)
39 ? GUIStyle.SubHeadingFont
45 protected static readonly Regex
bbTagRegex =
new Regex(
@"\[(.+?)\]",
46 RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
50 Point cachedContainerSize = Point.Zero;
51 List<BBWord> bbWords =
new List<BBWord>();
59 cachedContainerSize = Point.Zero;
69 var matches =
new Stack<Match>(
bbTagRegex.Matches(bbCode).Reverse());
70 Match? nextTag =
null;
71 matches.TryPop(out nextTag);
74 for (
int i = 0; i < bbCode.Length; i++)
76 char currChar = bbCode[i];
77 currTagType = tagStack.TryPeek(out var t) ? t :
BBWord.
TagType.None;
79 bool charIsCJK = TextManager.IsCJK($
"{currChar}");
80 bool wordEnd =
char.IsWhiteSpace(currChar) || charIsCJK;
81 int reachedTagLength = 0;
82 if (nextTag is { Index:
int tagIndex, Length:
int tagLength }
85 reachedTagLength = tagLength;
86 string tagStr = nextTag.Value.Replace(
"[",
"").Replace(
"]",
"").Trim();
87 bool isClosing = tagStr.StartsWith(
"/");
88 tagStr = tagStr.Replace(
"/",
"").Trim().ToLowerInvariant();
101 if (currTagType == tagType)
108 tagStack.Push(tagType);
113 if (wordEnd || reachedTagLength > 0)
115 string word = bbCode[wordStart..i];
116 if (charIsCJK) { word = bbCode[wordStart..(i + 1)]; }
117 else if (
char.IsWhiteSpace(currChar) && currChar !=
'\n') { word +=
" "; }
119 if (!word.IsNullOrEmpty())
121 bbWords.Add(
new BBWord(word, currTagType));
123 else if (currChar ==
'\n')
128 if (reachedTagLength > 0)
130 i += reachedTagLength - 1;
131 nextTag = matches.TryPop(out var tag) ? tag :
null;
138 currTagType = tagStack.TryPeek(out var ft) ? ft :
BBWord.
TagType.None;
139 string finalWord = bbCode[wordStart..];
140 if (!finalWord.IsNullOrEmpty())
142 bbWords.Add(
new BBWord(finalWord, currTagType));
151 recalculate(component);
152 Vector2 currPos = Vector2.Zero;
153 Vector2 rectPos = component.
Rect.Location.ToVector2();
154 for (
int i = 0; i < bbWords.Count; i++)
156 var bbWord = bbWords[i];
158 && currPos.X + bbWord.Size.X >= component.
Rect.Width)
161 currPos = (0.0f, currPos.Y + bbWord.Size.Y);
164 bbWord.Font.DrawString(
167 (currPos + rectPos).ToPoint().ToVector2(),
168 GUIStyle.TextColorNormal,
173 || (i < bbWords.Count - 1 &&
179 currPos = (0.0f, currPos.Y + bbWord.Size.Y);
183 currPos.X += bbWord.Size.X;
189 (int)(currPos.Y + bbWords.LastOrDefault().Size.Y));
195 $
"GetWorkshopItemLongDescriptionFor{workshopItem.Id.Value}",
196 SteamManager.Workshop.GetItemAsap(workshopItem.Id.Value, withLongDescription:
true),
199 if (!t.TryGetResult(out Option<Steamworks.Ugc.Item> workshopItemWithDescription)) {
return; }
201 bbCode = workshopItemWithDescription.TryUnwrap(out var item) ? (item.Description ??
"") :
"";
RectTransform RectTransform
GUIComponent that can be used to render custom content on the UI
Vector2 MeasureString(LocalizedString str, bool removeExtraSpacing=false)
void RecalculateChildren()
GUIFrame Content
A frame that contains the contents of the listbox. The frame itself is not rendered.
void UpdateScrollBarSize()