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;
foreach (var code in appliedCodes)
code.Token = this;
}
///
/// 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) {
return this.AppliedCodes.Select(c => c.GetColor(defaultPick)).FirstOrDefault(c => c.HasValue);
}
///
/// 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) {
return this.AppliedCodes.Select(c => c.GetFont(defaultPick)).FirstOrDefault(f => f != null);
}
///
/// 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, pos, font, color, scale, depth);
}
///
/// Draws a given character using this token's formatting options.
///
/// The time
/// The sprite batch to use
/// The character to draw
/// A single-character string that contains 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, char c, string cString, int indexInToken, Vector2 pos, GenericFont font, Color color, float scale, float depth) {
foreach (var code in this.AppliedCodes) {
if (code.DrawCharacter(time, batch, c, cString, indexInToken, ref pos, font, ref color, ref scale, depth))
return;
}
// if no code drew, we have to do it ourselves
font.DrawString(batch, cString, 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));
}
}
}