mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-26 06:28:35 +01:00
added link formatting codes!
This commit is contained in:
parent
9ce01bc6f2
commit
7f0a8289e3
7 changed files with 79 additions and 7 deletions
|
@ -61,7 +61,7 @@ namespace Demos {
|
||||||
IsHidden = true
|
IsHidden = true
|
||||||
});
|
});
|
||||||
|
|
||||||
selection.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Select the demo you want to see below using your mouse, touch input, your keyboard or a controller. Check the demos' source code for more in-depth explanations of their functionality."));
|
selection.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Select the demo you want to see below using your mouse, touch input, your keyboard or a controller. Check the demos' <c CornflowerBlue><l https://github.com/Ellpeck/MLEM/tree/master/Demos>source code</l></c> for more in-depth explanations of their functionality or the <c CornflowerBlue><l https://github.com/Ellpeck/MLEM/wiki>wiki</l></c> for tutorials."));
|
||||||
selection.AddChild(new VerticalSpace(5));
|
selection.AddChild(new VerticalSpace(5));
|
||||||
foreach (var demo in Demos) {
|
foreach (var demo in Demos) {
|
||||||
selection.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), demo.Key, demo.Value.Item1) {
|
selection.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), demo.Key, demo.Value.Item1) {
|
||||||
|
|
|
@ -2,11 +2,14 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using MLEM.Extensions;
|
using MLEM.Extensions;
|
||||||
using MLEM.Font;
|
using MLEM.Font;
|
||||||
using MLEM.Formatting;
|
using MLEM.Formatting;
|
||||||
|
using MLEM.Formatting.Codes;
|
||||||
|
using MLEM.Input;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
using MLEM.Textures;
|
using MLEM.Textures;
|
||||||
using MLEM.Ui.Style;
|
using MLEM.Ui.Style;
|
||||||
|
@ -25,6 +28,7 @@ namespace MLEM.Ui.Elements {
|
||||||
public StyleProp<FormatSettings> FormatSettings;
|
public StyleProp<FormatSettings> FormatSettings;
|
||||||
public readonly TextFormatter Formatter;
|
public readonly TextFormatter Formatter;
|
||||||
public TokenizedString TokenizedText { get; private set; }
|
public TokenizedString TokenizedText { get; private set; }
|
||||||
|
public Token HoveredToken { get; private set; }
|
||||||
|
|
||||||
public StyleProp<Color> TextColor;
|
public StyleProp<Color> TextColor;
|
||||||
public StyleProp<float> TextScale;
|
public StyleProp<float> TextScale;
|
||||||
|
@ -42,6 +46,7 @@ namespace MLEM.Ui.Elements {
|
||||||
public TextCallback GetTextCallback;
|
public TextCallback GetTextCallback;
|
||||||
[Obsolete("Use the new text formatting system in MLEM.Formatting instead")]
|
[Obsolete("Use the new text formatting system in MLEM.Formatting instead")]
|
||||||
public TextModifier RenderedTextModifier = text => text;
|
public TextModifier RenderedTextModifier = text => text;
|
||||||
|
[Obsolete("Use the new text formatting system in MLEM.Formatting instead")]
|
||||||
public TimeSpan TimeIntoAnimation;
|
public TimeSpan TimeIntoAnimation;
|
||||||
|
|
||||||
public Paragraph(Anchor anchor, float width, TextCallback textCallback, bool centerText = false)
|
public Paragraph(Anchor anchor, float width, TextCallback textCallback, bool centerText = false)
|
||||||
|
@ -59,7 +64,17 @@ namespace MLEM.Ui.Elements {
|
||||||
this.AutoAdjustWidth = centerText;
|
this.AutoAdjustWidth = centerText;
|
||||||
this.CanBeSelected = false;
|
this.CanBeSelected = false;
|
||||||
this.CanBeMoused = false;
|
this.CanBeMoused = false;
|
||||||
|
|
||||||
this.Formatter = new TextFormatter(() => this.BoldFont, () => this.ItalicFont);
|
this.Formatter = new TextFormatter(() => this.BoldFont, () => this.ItalicFont);
|
||||||
|
this.Formatter.Codes.Add(new Regex("<l ([^>]+)>"), (f, m, r) => new LinkCode(m, r, 1 / 16F, 0.85F, t => t == this.HoveredToken, l => {
|
||||||
|
if (!this.Input.IsPressed(MouseButton.Left))
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
Process.Start(l.Match.Groups[1].Value);
|
||||||
|
} catch (Exception) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Vector2 CalcActualSize(RectangleF parentArea) {
|
protected override Vector2 CalcActualSize(RectangleF parentArea) {
|
||||||
|
@ -76,6 +91,8 @@ namespace MLEM.Ui.Elements {
|
||||||
|
|
||||||
this.TokenizedText = this.Formatter.Tokenize(this.RegularFont, this.text);
|
this.TokenizedText = this.Formatter.Tokenize(this.RegularFont, this.text);
|
||||||
this.TokenizedText.Split(this.RegularFont, size.X - this.ScaledPadding.Width, sc);
|
this.TokenizedText.Split(this.RegularFont, size.X - this.ScaledPadding.Width, sc);
|
||||||
|
this.CanBeMoused = this.TokenizedText.AllCodes.OfType<LinkCode>().Any();
|
||||||
|
|
||||||
var dims = this.TokenizedText.Measure(this.RegularFont) * sc;
|
var dims = this.TokenizedText.Measure(this.RegularFont) * sc;
|
||||||
return new Vector2(this.AutoAdjustWidth ? dims.X + this.ScaledPadding.Width : size.X, dims.Y + this.ScaledPadding.Height);
|
return new Vector2(this.AutoAdjustWidth ? dims.X + this.ScaledPadding.Width : size.X, dims.Y + this.ScaledPadding.Height);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +108,11 @@ namespace MLEM.Ui.Elements {
|
||||||
if (this.GetTextCallback != null)
|
if (this.GetTextCallback != null)
|
||||||
this.Text = this.GetTextCallback(this);
|
this.Text = this.GetTextCallback(this);
|
||||||
this.TimeIntoAnimation += time.ElapsedGameTime;
|
this.TimeIntoAnimation += time.ElapsedGameTime;
|
||||||
this.TokenizedText?.Update(time);
|
|
||||||
|
if (this.TokenizedText != null) {
|
||||||
|
this.TokenizedText.Update(time);
|
||||||
|
this.HoveredToken = this.TokenizedText.GetTokenUnderPos(this.RegularFont, this.DisplayArea.Location, this.Input.MousePosition.ToVector2(), this.TextScale * this.Scale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
|
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
|
||||||
|
|
29
MLEM/Formatting/Codes/LinkCode.cs
Normal file
29
MLEM/Formatting/Codes/LinkCode.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Font;
|
||||||
|
|
||||||
|
namespace MLEM.Formatting.Codes {
|
||||||
|
public class LinkCode : UnderlineCode {
|
||||||
|
|
||||||
|
private readonly Action<LinkCode> onSelected;
|
||||||
|
private readonly Func<Token, bool> isSelected;
|
||||||
|
|
||||||
|
public LinkCode(Match match, Regex regex, float thickness, float yOffset, Func<Token, bool> isSelected, Action<LinkCode> onSelected) : base(match, regex, thickness, yOffset) {
|
||||||
|
this.onSelected = onSelected;
|
||||||
|
this.isSelected = isSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(GameTime time) {
|
||||||
|
if (this.isSelected(this.Token))
|
||||||
|
this.onSelected(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool DrawCharacter(GameTime time, SpriteBatch batch, char c, string cString, int indexInToken, ref Vector2 pos, GenericFont font, ref Color color, ref float scale, float depth) {
|
||||||
|
// since we inherit from UnderlineCode, we can just call base if selected
|
||||||
|
return this.isSelected(this.Token) && base.DrawCharacter(time, batch, c, cString, indexInToken, ref pos, font, ref color, ref scale, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,8 +20,9 @@ namespace MLEM.Formatting.Codes {
|
||||||
// don't underline spaces at the end of lines
|
// don't underline spaces at the end of lines
|
||||||
if (c == ' ' && this.Token.Substring.Length > indexInToken + 1 && this.Token.Substring[indexInToken + 1] == '\n')
|
if (c == ' ' && this.Token.Substring.Length > indexInToken + 1 && this.Token.Substring[indexInToken + 1] == '\n')
|
||||||
return false;
|
return false;
|
||||||
var width = font.MeasureString(cString).X * scale;
|
var size = font.MeasureString(cString) * scale;
|
||||||
batch.Draw(batch.GetBlankTexture(), new RectangleF(pos.X, pos.Y + this.yOffset * font.LineHeight - this.thickness * scale, width, this.thickness * scale), color);
|
var thicc = size.Y * this.thickness;
|
||||||
|
batch.Draw(batch.GetBlankTexture(), new RectangleF(pos.X, pos.Y + this.yOffset * size.Y - thicc, size.X, thicc), color);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ namespace MLEM.Formatting {
|
||||||
this.Codes.Add(new Regex("<b>"), (f, m, r) => new FontCode(m, r, boldFont?.Invoke()));
|
this.Codes.Add(new Regex("<b>"), (f, m, r) => new FontCode(m, r, boldFont?.Invoke()));
|
||||||
this.Codes.Add(new Regex("<i>"), (f, m, r) => new FontCode(m, r, italicFont?.Invoke()));
|
this.Codes.Add(new Regex("<i>"), (f, m, r) => new FontCode(m, r, italicFont?.Invoke()));
|
||||||
this.Codes.Add(new Regex(@"<s(?: #([0-9\w]{6,8}) (([+-.0-9]*)))?>"), (f, m, r) => new ShadowCode(m, r, m.Groups[1].Success ? ColorExtensions.FromHex(m.Groups[1].Value) : Color.Black, new Vector2(float.TryParse(m.Groups[2].Value, out var offset) ? offset : 2)));
|
this.Codes.Add(new Regex(@"<s(?: #([0-9\w]{6,8}) (([+-.0-9]*)))?>"), (f, m, r) => new ShadowCode(m, r, m.Groups[1].Success ? ColorExtensions.FromHex(m.Groups[1].Value) : Color.Black, new Vector2(float.TryParse(m.Groups[2].Value, out var offset) ? offset : 2)));
|
||||||
this.Codes.Add(new Regex("<u>"), (f, m, r) => new UnderlineCode(m, r, 2, 0.85F));
|
this.Codes.Add(new Regex("<u>"), (f, m, r) => new UnderlineCode(m, r, 1 / 16F, 0.85F));
|
||||||
this.Codes.Add(new Regex("</(b|i|s|u)>"), (f, m, r) => new FontCode(m, r, null));
|
this.Codes.Add(new Regex("</(b|i|s|u|l)>"), (f, m, r) => new FontCode(m, r, null));
|
||||||
|
|
||||||
// color codes
|
// color codes
|
||||||
foreach (var c in typeof(Color).GetProperties()) {
|
foreach (var c in typeof(Color).GetProperties()) {
|
||||||
|
|
|
@ -61,6 +61,27 @@ namespace MLEM.Formatting {
|
||||||
code.Update(time);
|
code.Update(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Token GetTokenUnderPos(GenericFont font, Vector2 stringPos, Vector2 target, float scale) {
|
||||||
|
var innerOffset = new Vector2();
|
||||||
|
foreach (var token in this.Tokens) {
|
||||||
|
var split = token.Substring.Split('\n');
|
||||||
|
for (var i = 0; i < split.Length; i++) {
|
||||||
|
var size = font.MeasureString(split[i]) * scale;
|
||||||
|
var lineArea = new RectangleF(stringPos + innerOffset, size);
|
||||||
|
if (lineArea.Contains(target))
|
||||||
|
return token;
|
||||||
|
|
||||||
|
if (i < split.Length - 1) {
|
||||||
|
innerOffset.X = 0;
|
||||||
|
innerOffset.Y += font.LineHeight * scale;
|
||||||
|
} else {
|
||||||
|
innerOffset.X += size.X;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void Draw(GameTime time, SpriteBatch batch, Vector2 pos, GenericFont font, Color color, float scale, float depth) {
|
public void Draw(GameTime time, SpriteBatch batch, Vector2 pos, GenericFont font, Color color, float scale, float depth) {
|
||||||
var innerOffset = new Vector2();
|
var innerOffset = new Vector2();
|
||||||
foreach (var token in this.Tokens) {
|
foreach (var token in this.Tokens) {
|
||||||
|
|
Loading…
Reference in a new issue