1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-29 15:58:33 +01:00

Compare commits

...

3 commits

5 changed files with 96 additions and 21 deletions

View file

@ -21,6 +21,8 @@ Additions
- Added SingleRandom and SeedSource - Added SingleRandom and SeedSource
- Added TokenizedString.GetArea - Added TokenizedString.GetArea
- Added InputHandler.WasPressedForLess and related methods as well as InputHandler.IsPressedIgnoreRepeats - Added InputHandler.WasPressedForLess and related methods as well as InputHandler.IsPressedIgnoreRepeats
- Added RandomExtensions.NextSingle with minimum and maximum values
- Added subscript and superscript formatting codes
- **Added the ability to find paths to one of multiple goals using AStar** - **Added the ability to find paths to one of multiple goals using AStar**
Improvements Improvements
@ -35,6 +37,7 @@ Improvements
- Allow explicitly specifying each region for extended auto tiles - Allow explicitly specifying each region for extended auto tiles
- Added a generic version of IGenericDataHolder.SetData - Added a generic version of IGenericDataHolder.SetData
- Allow formatting codes to have an arbitrary custom width - Allow formatting codes to have an arbitrary custom width
- Allow initializing text formatters without default codes and macros
- **Drastically improved StaticSpriteBatch batching performance** - **Drastically improved StaticSpriteBatch batching performance**
- **Made GenericFont and TokenizedString support UTF-32 characters like emoji** - **Made GenericFont and TokenizedString support UTF-32 characters like emoji**

View file

@ -18,7 +18,7 @@ namespace Demos {
"You can write in <b>bold</i>, <i>italics</i>, <u>with an underline</u>, <st>strikethrough</st>, with a <s #000000 4>drop shadow</s> whose <s #ff0000 4>color</s> and <s #000000 10>offset</s> you can modify in each application of the code, or with various types of <b>combined <c Pink>formatting</c> codes</b>.\n\n" + "You can write in <b>bold</i>, <i>italics</i>, <u>with an underline</u>, <st>strikethrough</st>, with a <s #000000 4>drop shadow</s> whose <s #ff0000 4>color</s> and <s #000000 10>offset</s> you can modify in each application of the code, or with various types of <b>combined <c Pink>formatting</c> codes</b>.\n\n" +
"You can apply <c CornflowerBlue>custom</c> <c Yellow>colors</c> to text, including all default <c Orange>MonoGame colors</c> and <c #aabb00>inline custom colors</c>.\n\n" + "You can apply <c CornflowerBlue>custom</c> <c Yellow>colors</c> to text, including all default <c Orange>MonoGame colors</c> and <c #aabb00>inline custom colors</c>.\n\n" +
"You can also use animations like <a wobbly>a wobbly one</a>, as well as create custom ones using the <a wobbly>Code class</a>.\n\n" + "You can also use animations like <a wobbly>a wobbly one</a>, as well as create custom ones using the <a wobbly>Code class</a>.\n\n" +
"You can also display <i grass> icons in your text!\n\n" + "You can also display <i grass> icons in your text, and use super<sup>script</sup> or sub<sub>script</sub> formatting!\n\n" +
"Additionally, the text formatter has various methods for interacting with the text, like custom behaviors when hovering over certain parts, and more."; "Additionally, the text formatter has various methods for interacting with the text, like custom behaviors when hovering over certain parts, and more.";
private const float Scale = 0.5F; private const float Scale = 0.5F;
private const float Width = 0.9F; private const float Width = 0.9F;

View file

@ -55,5 +55,37 @@ namespace MLEM.Extensions {
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
} }
/// <summary>
/// Returns a random floating-point number that is greater than or equal to 0, and less than <paramref name="maxValue"/>.
/// </summary>
/// <param name="random">The random.</param>
/// <param name="maxValue">The (exclusive) maximum value.</param>
/// <returns>A single-precision floating point number that is greater than or equal to 0, and less than <paramref name="maxValue"/>.</returns>
public static float NextSingle(this Random random, float maxValue) {
return maxValue * random.NextSingle();
}
/// <summary>
/// Returns a random floating-point number that is greater than or equal to <paramref name="minValue"/>, and less than <paramref name="maxValue"/>.
/// </summary>
/// <param name="random">The random.</param>
/// <param name="minValue">The (inclusive) minimum value.</param>
/// <param name="maxValue">The (exclusive) maximum value.</param>
/// <returns>A single-precision floating point number that is greater than or equal to <paramref name="minValue"/>, and less than <paramref name="maxValue"/>.</returns>
public static float NextSingle(this Random random, float minValue, float maxValue) {
return (maxValue - minValue) * random.NextSingle() + minValue;
}
#if !NET6_0_OR_GREATER
/// <summary>
/// Returns a random floating-point number that is greater than or equal to 0, and less than 1.
/// </summary>
/// <param name="random">The random.</param>
/// <returns>A single-precision floating point number that is greater than or equal to 0, and less than 1.</returns>
public static float NextSingle(this Random random) {
return (float) random.NextDouble();
}
#endif
} }
} }

View file

@ -0,0 +1,24 @@
using System.Text.RegularExpressions;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Font;
namespace MLEM.Formatting.Codes {
/// <inheritdoc />
public class SubSupCode : Code {
private readonly float offset;
/// <inheritdoc />
public SubSupCode(Match match, Regex regex, float offset) : base(match, regex) {
this.offset = offset;
}
/// <inheritdoc />
public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, ref Vector2 pos, GenericFont font, ref Color color, ref float scale, float depth) {
pos.Y += this.offset * font.LineHeight * scale;
return false;
}
}
}

View file

@ -29,38 +29,54 @@ namespace MLEM.Formatting {
public readonly Dictionary<Regex, Macro> Macros = new Dictionary<Regex, Macro>(); public readonly Dictionary<Regex, Macro> Macros = new Dictionary<Regex, Macro>();
/// <summary> /// <summary>
/// Creates a new text formatter with a set of default formatting codes. /// Creates a new text formatter with an optional set of default formatting codes.
/// </summary> /// </summary>
public TextFormatter() { /// <param name="hasFontModifiers">Whether default font modifier codes should be added, including bold, italic, strikethrough, shadow, subscript, and more.</param>
// font codes /// <param name="hasColors">Whether default color codes should be added, including all <see cref="Color"/> values and the ability to use custom colors.</param>
this.Codes.Add(new Regex("<b>"), (f, m, r) => new FontCode(m, r, fnt => fnt.Bold)); /// <param name="hasAnimations">Whether default animation codes should be added, namely the wobbly animation.</param>
this.Codes.Add(new Regex("<i>"), (f, m, r) => new FontCode(m, r, fnt => fnt.Italic)); /// <param name="hasMacros">Whether default macros should be added, including TeX's ~ non-breaking space and more.</param>
this.Codes.Add(new Regex(@"<s(?: #([0-9\w]{6,8}) (([+-.0-9]*)))?>"), (f, m, r) => new ShadowCode(m, r, public TextFormatter(bool hasFontModifiers = true, bool hasColors = true, bool hasAnimations = true, bool hasMacros = true) {
m.Groups[1].Success ? ColorHelper.FromHexString(m.Groups[1].Value) : Color.Black, // general font modifier codes
new Vector2(float.TryParse(m.Groups[2].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var offset) ? offset : 2))); if (hasFontModifiers) {
this.Codes.Add(new Regex("<u>"), (f, m, r) => new UnderlineCode(m, r, 1 / 16F, 0.85F)); this.Codes.Add(new Regex("<b>"), (f, m, r) => new FontCode(m, r, fnt => fnt.Bold));
this.Codes.Add(new Regex("<st>"), (f, m, r) => new UnderlineCode(m, r, 1 / 16F, 0.55F)); this.Codes.Add(new Regex("<i>"), (f, m, r) => new FontCode(m, r, fnt => fnt.Italic));
this.Codes.Add(new Regex(@"<s(?: #([0-9\w]{6,8}) (([+-.0-9]*)))?>"), (f, m, r) => new ShadowCode(m, r,
m.Groups[1].Success ? ColorHelper.FromHexString(m.Groups[1].Value) : Color.Black,
new Vector2(float.TryParse(m.Groups[2].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var offset) ? offset : 2)));
this.Codes.Add(new Regex("<u>"), (f, m, r) => new UnderlineCode(m, r, 1 / 16F, 0.85F));
this.Codes.Add(new Regex("<st>"), (f, m, r) => new UnderlineCode(m, r, 1 / 16F, 0.55F));
this.Codes.Add(new Regex(@"<sub(?: ([+-.0-9]+))?>"), (f, m, r) => new SubSupCode(m, r,
float.TryParse(m.Groups[1].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var off) ? off : 0.15F));
this.Codes.Add(new Regex(@"<sup(?: ([+-.0-9]+))?>"), (f, m, r) => new SubSupCode(m, r,
float.TryParse(m.Groups[1].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var off) ? -off : -0.25F));
}
// color codes // color codes
foreach (var c in typeof(Color).GetProperties()) { if (hasColors) {
if (c.GetGetMethod().IsStatic) { foreach (var c in typeof(Color).GetProperties()) {
var value = (Color) c.GetValue(null); if (c.GetGetMethod().IsStatic) {
this.Codes.Add(new Regex($"<c {c.Name}>"), (f, m, r) => new ColorCode(m, r, value)); var value = (Color) c.GetValue(null);
this.Codes.Add(new Regex($"<c {c.Name}>"), (f, m, r) => new ColorCode(m, r, value));
}
} }
this.Codes.Add(new Regex(@"<c #([0-9\w]{6,8})>"), (f, m, r) => new ColorCode(m, r, ColorHelper.FromHexString(m.Groups[1].Value)));
} }
this.Codes.Add(new Regex(@"<c #([0-9\w]{6,8})>"), (f, m, r) => new ColorCode(m, r, ColorHelper.FromHexString(m.Groups[1].Value)));
// animation codes // animation codes
this.Codes.Add(new Regex(@"<a wobbly(?: ([+-.0-9]*) ([+-.0-9]*))?>"), (f, m, r) => new WobblyCode(m, r, if (hasAnimations) {
float.TryParse(m.Groups[1].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var mod) ? mod : 5, this.Codes.Add(new Regex(@"<a wobbly(?: ([+-.0-9]*) ([+-.0-9]*))?>"), (f, m, r) => new WobblyCode(m, r,
float.TryParse(m.Groups[2].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var heightMod) ? heightMod : 1 / 8F)); float.TryParse(m.Groups[1].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var mod) ? mod : 5,
float.TryParse(m.Groups[2].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var heightMod) ? heightMod : 1 / 8F));
}
// control codes // control codes
this.Codes.Add(new Regex(@"</(\w+)>"), (f, m, r) => new SimpleEndCode(m, r, m.Groups[1].Value)); this.Codes.Add(new Regex(@"</(\w+)>"), (f, m, r) => new SimpleEndCode(m, r, m.Groups[1].Value));
// macros // macros
this.Macros.Add(new Regex("~"), (f, m, r) => GenericFont.Nbsp.ToString()); if (hasMacros) {
this.Macros.Add(new Regex("<n>"), (f, m, r) => '\n'.ToString()); this.Macros.Add(new Regex("~"), (f, m, r) => GenericFont.Nbsp.ToString());
this.Macros.Add(new Regex("<n>"), (f, m, r) => '\n'.ToString());
}
} }
/// <summary> /// <summary>