using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MLEM.Font; using MLEM.Formatting.Codes; using MLEM.Misc; namespace MLEM.Formatting { /// /// A part of a that has a certain list of formatting codes applied. /// public class Token : GenericDataHolder { /// /// The formatting codes that are applied on this token. /// public readonly Code[] AppliedCodes; /// /// The index in the that this token starts at. /// public readonly int Index; /// /// The index in the that this token starts at. /// public readonly int RawIndex; /// /// The substring that this token contains. /// public readonly string Substring; /// /// The string that is displayed by this token. If the tokenized string has been or has been used, this string will contain the newline characters. /// public string DisplayString => this.ModifiedSubstring ?? this.Substring; /// /// The , but split at newline characters /// public string[] SplitDisplayString { get; internal set; } /// /// The substring that this token contains, without the formatting codes removed. /// public readonly string RawSubstring; internal RectangleF[] Area; internal string ModifiedSubstring; internal float[] InnerOffsets; internal Token(Code[] appliedCodes, int index, int rawIndex, string substring, string rawSubstring) { this.AppliedCodes = appliedCodes; this.Index = index; this.RawIndex = rawIndex; this.Substring = substring; this.RawSubstring = rawSubstring; } /// /// Get the color that this token will be rendered with /// /// The default color, if none is specified /// The color to render with public Color GetColor(Color defaultPick) { foreach (var code in this.AppliedCodes) { var color = code.GetColor(defaultPick); if (color.HasValue) return color.Value; } return defaultPick; } /// /// Get the font that this token will be rendered with /// /// The default font, if none is specified /// The font to render with public GenericFont GetFont(GenericFont defaultPick) { foreach (var code in this.AppliedCodes) { var font = code.GetFont(defaultPick); if (font != null) return font; } return defaultPick; } /// /// Returns the width of the token itself, including all of the instances that this token contains. /// Note that this method does not return the width of this token's , but only the width that the codes themselves take up. /// /// The font to use for calculating the width. /// The width of this token itself. public float GetSelfWidth(GenericFont font) { var ret = 0F; foreach (var code in this.AppliedCodes) ret += code.GetSelfWidth(font); return ret; } /// /// Draws the token itself, including all of the instances that this token contains. /// Note that, to draw the token's actual string, is used. /// /// The time /// The sprite batch to use /// The position to draw the token at /// The font to use to draw /// The color to draw with /// The scale to draw at /// The depth to draw at public void DrawSelf(GameTime time, SpriteBatch batch, Vector2 pos, GenericFont font, Color color, float scale, float depth) { foreach (var code in this.AppliedCodes) code.DrawSelf(time, batch, this, pos, font, color, scale, depth); } /// /// Draws a given code point using this token's formatting options. /// /// The time /// The sprite batch to use /// The code point of the character to draw /// The string representation of the character to draw /// The index within this token that the character is at /// The position to draw the token at /// The font to use to draw /// The color to draw with /// The scale to draw at /// The depth to draw at public void DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, int indexInToken, Vector2 pos, GenericFont font, Color color, float scale, float depth) { foreach (var code in this.AppliedCodes) { if (code.DrawCharacter(time, batch, codePoint, character, this, indexInToken, ref pos, font, ref color, ref scale, depth)) return; } // if no code drew, we have to do it ourselves font.DrawString(batch, character, pos, color, 0, Vector2.Zero, scale, SpriteEffects.None, depth); } /// /// Gets a list of rectangles that encompass this token's area. /// Note that more than one rectangle is only returned if the string has been split. /// This can be used to invoke events when the mouse is hovered over the token, for example. /// /// The position that the string is drawn at /// The scale that the string is drawn at /// A set of rectangles that this token contains public IEnumerable GetArea(Vector2 stringPos, float scale) { return this.Area.Select(a => new RectangleF(stringPos + a.Location * scale, a.Size * scale)); } } }