You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
9.2 KiB
C#

using System;
using System.IO;
namespace Otter {
/// <summary>
/// Graphic used to display simple text. Much faster than RichText, but more limited options.
/// </summary>
public class Text : Graphic {
#region Private Fields
TextStyle textStyle;
#endregion
#region Private Properties
bool isUsingShadow {
get {
return ShadowX != 0 || ShadowY != 0;
}
}
bool isUsingOutline {
get {
return OutlineThickness > 0;
}
}
#endregion
#region Public Fields
/// <summary>
/// The color of the text shadow.
/// </summary>
public Color ShadowColor = Color.Black;
/// <summary>
/// The X position of the shadow.
/// </summary>
public int ShadowX;
/// <summary>
/// The Y position of the shadow.
/// </summary>
public int ShadowY;
/// <summary>
/// The Color of the outline.
/// </summary>
public Color OutlineColor = Color.Black;
/// <summary>
/// The thickness of the outline.
/// </summary>
public int OutlineThickness;
/// <summary>
/// The quality of the outline. Higher quality is more rendering passes!
/// </summary>
public TextOutlineQuality OutlineQuality = TextOutlineQuality.Good;
#endregion
#region Public Properties
/// <summary>
/// The displayed string.
/// </summary>
public string String {
get {
return text.DisplayedString;
}
set {
text.DisplayedString = value;
NeedsUpdate = true;
Lines = text.DisplayedString.Split('\n').Length;
UpdateDrawable();
}
}
/// <summary>
/// The number of lines in the text.
/// </summary>
public int Lines { get; private set; }
/// <summary>
/// The amount of space between each line of text.
/// </summary>
public float LineSpacing {
get { return text.Font.GetLineSpacing(text.CharacterSize); }
}
/// <summary>
/// The font size.
/// </summary>
public int FontSize {
get { return (int)text.CharacterSize; }
set {
text.CharacterSize = (uint)value;
UpdateDrawable();
}
}
/// <summary>
/// Set the TextStyle (bold, italic, underline.)
/// </summary>
public TextStyle TextStyle {
get { return textStyle; }
set {
textStyle = value;
text.Style = (SFML.Graphics.Text.Styles)TextStyle;
NeedsUpdate = true;
UpdateDrawable();
}
}
/// <summary>
/// Set both ShadowX and ShadowY.
/// </summary>
public int Shadow {
set {
ShadowX = value; ShadowY = value;
}
}
/// <summary>
/// Get the actual center Y of the Text.
/// </summary>
public float CenterY {
get {
return HalfHeight + BoundsTop;
}
}
/// <summary>
/// The top bounds of the Text.
/// </summary>
public float BoundsTop {
get {
return text.GetLocalBounds().Top;
}
}
/// <summary>
/// The left bounds of the Text.
/// </summary>
public float BoundsLeft {
get {
return text.GetLocalBounds().Left;
}
}
#endregion
#region Constructors
/// <summary>
/// Create a new Text object.
/// </summary>
/// <param name="str">The string to display.</param>
/// <param name="font">The file path to the font to use.</param>
/// <param name="size">The size of the font.</param>
public Text(string str, string font = "", int size = 16)
: base() {
Initialize(str, font, size);
}
/// <summary>
/// Create a new Text object.
/// </summary>
/// <param name="str">The string to display.</param>
/// <param name="font">The stream to load the font to use.</param>
/// <param name="size">The size of the font.</param>
public Text(string str, Stream font, int size = 16)
: base() {
Initialize(str, font, size);
}
/// <summary>
/// Create a new Text object.
/// </summary>
/// <param name="str">The string to display.</param>
/// <param name="font">The Font to use.</param>
/// <param name="size">The size of the font.</param>
public Text(string str, Font font, int size = 16) : base() {
Initialize(str, font.font, size);
}
/// <summary>
/// Create a new Text object.
/// </summary>
/// <param name="str">The string to display.</param>
/// <param name="size">The size of the font.</param>
public Text(string str, int size = 16) : this(str, "", size) { }
/// <summary>
/// Create a new Text object.
/// </summary>
/// <param name="size">The size of the font.</param>
public Text(int size = 16) : this("", "", size) { }
#endregion
#region Private Methods
void Initialize(string str, object font, int size) {
if (size < 0) throw new ArgumentException("Font size must be greater than 0.");
if (font is string)
{
this.font = (string)font == "" ? Fonts.DefaultFont : Fonts.Load((string)font);
}
else if (font is Font)
{
this.font = ((Font) font).font;
}
else if (font is SFML.Graphics.Font) {
this.font = (SFML.Graphics.Font)font;
}
else
{
this.font = Fonts.Load((Stream) font);
}
text = new SFML.Graphics.Text(str, this.font, (uint)size);
String = str;
Name = "Text";
SFMLDrawable = text;
}
protected override void UpdateDrawable() {
base.UpdateDrawable();
Width = (int)text.GetLocalBounds().Width;
Height = (int)text.GetLocalBounds().Height;
}
#endregion
#region Public Methods
/// <summary>
/// Center the Text's origin. This factors in the Text's local bounds.
/// </summary>
public void CenterTextOrigin() {
CenterTextOriginX();
CenterTextOriginY();
}
/// <summary>
/// Center the Text's X origin. This factors in the Text's left bounds.
/// </summary>
public void CenterTextOriginX() {
OriginX = HalfWidth + BoundsLeft;
}
/// <summary>
/// Center the Text's Y origin. This factors in the Text's top bounds.
/// </summary>
public void CenterTextOriginY() {
OriginY = HalfHeight + BoundsTop;
}
/// <summary>
/// Draw the Text.
/// </summary>
/// <param name="x">The X position offset.</param>
/// <param name="y">The Y position offset.</param>
public override void Render(float x = 0, float y = 0) {
if (isUsingOutline) {
var outlineColor = new Color(OutlineColor);
outlineColor.A = Color.A;
text.Color = outlineColor.SFMLColor;
var angleIncrement = (int)OutlineQuality;
for (float o = OutlineThickness * 0.5f; o < OutlineThickness; o += 0.5f) {
for (int a = 0; a < 360; a += angleIncrement) {
var rx = x + Util.PolarX(a, o);
var ry = y + Util.PolarY(a, o);
base.Render(rx, ry);
}
}
}
if (isUsingShadow) {
var shadowColor = new Color(ShadowColor);
shadowColor.A = Color.A;
text.Color = shadowColor.SFMLColor;
base.Render(x + ShadowX, y + ShadowY);
}
text.Color = Color.SFMLColor;
base.Render(x, y);
}
#endregion
#region Internal
internal SFML.Graphics.Text text;
internal SFML.Graphics.Font font;
#endregion
}
#region Enum
[Flags]
public enum TextStyle {
Regular = 0,
Bold = 1,
Italic = 2,
Underlined = 4,
}
public enum TextOutlineQuality {
Good = 45,
Better = 30,
Best = 15,
Absurd = 10
}
#endregion
}