diff --git a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs new file mode 100644 index 000000000..1618687f0 --- /dev/null +++ b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs @@ -0,0 +1,200 @@ +using Dalamud.Game.Text.SeStringHandling.Payloads; + +namespace Dalamud.Game.Text.SeStringHandling +{ + /// + /// Helper class to build SeStrings using a builder pattern. + /// + public class SeStringBuilder + { + /// + /// Gets the built SeString. + /// + public SeString BuiltString { get; init; } = new SeString(); + + /// + /// Append another SeString to the builder. + /// + /// The SeString to append. + /// The current builder. + public SeStringBuilder Append(SeString toAppend) + { + this.BuiltString.Append(toAppend); + return this; + } + + /// + /// Append raw text to the builder. + /// + /// The raw text. + /// The current builder. + public SeStringBuilder Append(string text) => this.AddText(text); + + /// + /// Append raw text to the builder. + /// + /// The raw text. + /// The current builder. + public SeStringBuilder AddText(string text) => this.Add(new TextPayload(text)); + + /// + /// Start colored text in the current builder. + /// + /// The text color. + /// The current builder. + public SeStringBuilder AddUiForeground(ushort colorKey) => this.Add(new UIForegroundPayload(colorKey)); + + /// + /// Turn off a previous colored text. + /// + /// The current builder. + public SeStringBuilder AddUiForegroundOff() => this.Add(UIForegroundPayload.UIForegroundOff); + + /// + /// Add colored text to the current builder. + /// + /// The raw text. + /// The text color. + /// The current builder. + public SeStringBuilder AddUiForeground(string text, ushort colorKey) + { + this.AddUiForeground(colorKey); + this.AddText(text); + return this.AddUiForegroundOff(); + } + + /// + /// Start an UiGlow in the current builder. + /// + /// The glow color. + /// The current builder. + public SeStringBuilder AddUiGlow(ushort colorKey) => this.Add(new UIGlowPayload(colorKey)); + + /// + /// Turn off a previous UiGlow. + /// + /// The current builder. + public SeStringBuilder AddUiGlowOff() => this.Add(UIGlowPayload.UIGlowOff); + + /// + /// Add glowing text to the current builder. + /// + /// The raw text. + /// The glow color. + /// The current builder. + public SeStringBuilder AddUiGlow(string text, ushort colorKey) + { + this.AddUiGlow(colorKey); + this.AddText(text); + return this.AddUiGlowOff(); + } + + /// + /// Add an icon to the builder. + /// + /// The icon to add. + /// The current builder. + public SeStringBuilder AddIcon(BitmapFontIcon icon) => this.Add(new IconPayload(icon)); + + /// + /// Add an item link to the builder. + /// + /// The item ID. + /// Whether or not the item is high quality. + /// Override for the item's name. + /// The current builder. + public SeStringBuilder AddItemLink(uint itemId, bool isHq, string? itemNameOverride = null) => + this.Add(new ItemPayload(itemId, isHq, itemNameOverride)); + + /// + /// Add italicized raw text to the builder. + /// + /// The raw text. + /// The current builder. + public SeStringBuilder AddItalics(string text) + { + this.Add(EmphasisItalicPayload.ItalicsOn); + this.AddText(text); + return this.Add(EmphasisItalicPayload.ItalicsOff); + } + + /// + /// Turn italics on. + /// + /// The current builder. + public SeStringBuilder AddItalicsOn() => this.Add(EmphasisItalicPayload.ItalicsOn); + + /// + /// Turn italics off. + /// + /// The current builder. + public SeStringBuilder AddItalicsOff() => this.Add(EmphasisItalicPayload.ItalicsOff); + + /// + /// Add a map link payload to the builder. + /// + /// The id of the TerritoryType entry for this link. + /// The id of the Map entry for this link. + /// The internal raw x-coordinate for this link. + /// The internal raw y-coordinate for this link. + /// The current builder. + public SeStringBuilder AddMapLink(uint territoryTypeId, uint mapId, int rawX, int rawY) => + this.Add(new MapLinkPayload(territoryTypeId, mapId, rawX, rawY)); + + /// + /// Add a map link payload to the builder. + /// + /// The id of the TerritoryType entry for this link. + /// The id of the Map entry for this link. + /// The human-readable x-coordinate for this link. + /// The human-readable y-coordinate for this link. + /// An optional offset to account for rounding and truncation errors; it is best to leave this untouched in most cases. + /// The current builder. + public SeStringBuilder AddMapLink( + uint territoryTypeId, uint mapId, float niceXCoord, float niceYCoord, float fudgeFactor = 0.05f) => + this.Add(new MapLinkPayload(territoryTypeId, mapId, niceXCoord, niceYCoord, fudgeFactor)); + + /// + /// Add a quest link to the builder. + /// + /// The quest ID. + /// The current builder. + public SeStringBuilder AddQuestLink(uint questId) => this.Add(new QuestPayload(questId)); + + /// + /// Add a status effect link to the builder. + /// + /// The status effect ID. + /// The current builder. + public SeStringBuilder AddStatusLink(uint statusId) => this.Add(new StatusPayload(statusId)); + + /// + /// Add a payload to the builder. + /// + /// The payload to add. + /// The current builder. + public SeStringBuilder Add(Payload payload) + { + this.BuiltString.Payloads.Add(payload); + return this; + } + + /// + /// Return the built string. + /// + /// The built string. + public SeString Build() => this.BuiltString; + + /// + /// Encode the built string to bytes. + /// + /// The built string, encoded to UTF-8 bytes. + public byte[] Encode() => this.BuiltString.Encode(); + + /// + /// Return the text representation of this string. + /// + /// The text representation of this string. + public override string ToString() => this.BuiltString.ToString(); + } +}