mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-22 20:58:34 +01:00
added text animation
This commit is contained in:
parent
a46e8fce86
commit
b2b59aa78a
5 changed files with 95 additions and 27 deletions
|
@ -102,6 +102,12 @@ namespace Demos {
|
||||||
TextFormatting.FormattingCodes["tree"] = new FormattingCode(tree);
|
TextFormatting.FormattingCodes["tree"] = new FormattingCode(tree);
|
||||||
root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Additionally, you can create custom formatting codes that contain [Grass] images! Note that these images have to be square, or [Tree] bad things happen."));
|
root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Additionally, you can create custom formatting codes that contain [Grass] images! Note that these images have to be square, or [Tree] bad things happen."));
|
||||||
|
|
||||||
|
var animatedPar = root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Defining text animations as formatting codes is also possible, including [Wobbly]wobbly text[Unanimated] as well as a [Typing]dialogue-esc typing effect by default. Of course, more animations can be added though."));
|
||||||
|
root.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), "Reset Typing Animation") {
|
||||||
|
// to reset any animation, simply change the paragraph's TimeIntoAnimation
|
||||||
|
OnPressed = e => animatedPar.TimeIntoAnimation = TimeSpan.Zero
|
||||||
|
});
|
||||||
|
|
||||||
root.AddChild(new VerticalSpace(3));
|
root.AddChild(new VerticalSpace(3));
|
||||||
root.AddChild(new Paragraph(Anchor.AutoCenter, 1, "Text input:", true));
|
root.AddChild(new Paragraph(Anchor.AutoCenter, 1, "Text input:", true));
|
||||||
root.AddChild(new TextField(Anchor.AutoLeft, new Vector2(1, 10)) {
|
root.AddChild(new TextField(Anchor.AutoLeft, new Vector2(1, 10)) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
public bool AutoAdjustWidth;
|
public bool AutoAdjustWidth;
|
||||||
public TextCallback GetTextCallback;
|
public TextCallback GetTextCallback;
|
||||||
|
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)
|
||||||
: this(anchor, width, "", centerText) {
|
: this(anchor, width, "", centerText) {
|
||||||
|
@ -64,6 +65,7 @@ namespace MLEM.Ui.Elements {
|
||||||
base.Update(time);
|
base.Update(time);
|
||||||
if (this.GetTextCallback != null)
|
if (this.GetTextCallback != null)
|
||||||
this.Text = this.GetTextCallback(this);
|
this.Text = this.GetTextCallback(this);
|
||||||
|
this.TimeIntoAnimation += time.ElapsedGameTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw(GameTime time, SpriteBatch batch, float alpha) {
|
public override void Draw(GameTime time, SpriteBatch batch, float alpha) {
|
||||||
|
@ -78,7 +80,7 @@ namespace MLEM.Ui.Elements {
|
||||||
this.regularFont.DrawString(batch, this.splitText, pos, this.TextColor * alpha, 0, Vector2.Zero, sc, SpriteEffects.None, 0);
|
this.regularFont.DrawString(batch, this.splitText, pos, this.TextColor * alpha, 0, Vector2.Zero, sc, SpriteEffects.None, 0);
|
||||||
} else {
|
} else {
|
||||||
// if we have formatting codes, we should do it
|
// if we have formatting codes, we should do it
|
||||||
this.regularFont.DrawFormattedString(batch, pos, this.splitText, this.codeLocations, this.TextColor * alpha, sc, this.boldFont, this.italicFont);
|
this.regularFont.DrawFormattedString(batch, pos, this.splitText, this.codeLocations, this.TextColor * alpha, sc, this.boldFont, this.italicFont, 0, this.TimeIntoAnimation);
|
||||||
}
|
}
|
||||||
base.Draw(time, batch, alpha);
|
base.Draw(time, batch, alpha);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace MLEM.Formatting {
|
||||||
public readonly Color Color;
|
public readonly Color Color;
|
||||||
public readonly TextStyle Style;
|
public readonly TextStyle Style;
|
||||||
public readonly TextureRegion Icon;
|
public readonly TextureRegion Icon;
|
||||||
|
public readonly TextAnimation.DrawCharacter Animation;
|
||||||
|
|
||||||
public FormattingCode(Color color) {
|
public FormattingCode(Color color) {
|
||||||
this.Color = color;
|
this.Color = color;
|
||||||
|
@ -24,6 +25,11 @@ namespace MLEM.Formatting {
|
||||||
this.CodeType = Type.Icon;
|
this.CodeType = Type.Icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FormattingCode(TextAnimation.DrawCharacter animation) {
|
||||||
|
this.Animation = animation;
|
||||||
|
this.CodeType = Type.Animation;
|
||||||
|
}
|
||||||
|
|
||||||
public string GetReplacementString() {
|
public string GetReplacementString() {
|
||||||
return this.CodeType == Type.Icon ? TextFormatting.OneEmString : string.Empty;
|
return this.CodeType == Type.Icon ? TextFormatting.OneEmString : string.Empty;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +38,8 @@ namespace MLEM.Formatting {
|
||||||
|
|
||||||
Color,
|
Color,
|
||||||
Style,
|
Style,
|
||||||
Icon
|
Icon,
|
||||||
|
Animation
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
30
MLEM/Formatting/TextAnimation.cs
Normal file
30
MLEM/Formatting/TextAnimation.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Font;
|
||||||
|
|
||||||
|
namespace MLEM.Formatting {
|
||||||
|
public static class TextAnimation {
|
||||||
|
|
||||||
|
public static float WobbleModifier = 5;
|
||||||
|
public static float WobbleHeightModifier = 1 / 8F;
|
||||||
|
public static float TypingSpeed = 20;
|
||||||
|
|
||||||
|
public static readonly DrawCharacter Default = (font, batch, totalText, index, effectStartIndex, charSt, position, color, scale, layerDepth, timeIntoAnimation) => {
|
||||||
|
font.DrawString(batch, charSt, position, color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly DrawCharacter Wobbly = (font, batch, totalText, index, effectStartIndex, charSt, position, color, scale, layerDepth, timeIntoAnimation) => {
|
||||||
|
var offset = new Vector2(0, (float) Math.Sin(index + timeIntoAnimation.TotalSeconds * WobbleModifier) * font.LineHeight * WobbleHeightModifier * scale);
|
||||||
|
font.DrawString(batch, charSt, position + offset, color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly DrawCharacter Typing = (font, batch, totalText, index, effectStartIndex, charSt, position, color, scale, layerDepth, timeIntoAnimation) => {
|
||||||
|
if (timeIntoAnimation.TotalSeconds * TypingSpeed > index - effectStartIndex + 1)
|
||||||
|
font.DrawString(batch, charSt, position, color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
|
||||||
|
};
|
||||||
|
|
||||||
|
public delegate void DrawCharacter(IGenericFont font, SpriteBatch batch, string totalText, int index, int effectStartIndex, string charSt, Vector2 position, Color color, float scale, float layerDepth, TimeSpan timeIntoAnimation);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
@ -20,15 +21,22 @@ namespace MLEM.Formatting {
|
||||||
static TextFormatting() {
|
static TextFormatting() {
|
||||||
SetFormatIndicators('[', ']');
|
SetFormatIndicators('[', ']');
|
||||||
|
|
||||||
|
// style codes
|
||||||
FormattingCodes["regular"] = new FormattingCode(TextStyle.Regular);
|
FormattingCodes["regular"] = new FormattingCode(TextStyle.Regular);
|
||||||
FormattingCodes["italic"] = new FormattingCode(TextStyle.Italic);
|
FormattingCodes["italic"] = new FormattingCode(TextStyle.Italic);
|
||||||
FormattingCodes["bold"] = new FormattingCode(TextStyle.Bold);
|
FormattingCodes["bold"] = new FormattingCode(TextStyle.Bold);
|
||||||
|
|
||||||
|
// color codes
|
||||||
var colors = typeof(Color).GetProperties();
|
var colors = typeof(Color).GetProperties();
|
||||||
foreach (var color in colors) {
|
foreach (var color in colors) {
|
||||||
if (color.GetGetMethod().IsStatic)
|
if (color.GetGetMethod().IsStatic)
|
||||||
FormattingCodes[color.Name.ToLowerInvariant()] = new FormattingCode((Color) color.GetValue(null));
|
FormattingCodes[color.Name.ToLowerInvariant()] = new FormattingCode((Color) color.GetValue(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// animations
|
||||||
|
FormattingCodes["unanimated"] = new FormattingCode(TextAnimation.Default);
|
||||||
|
FormattingCodes["wobbly"] = new FormattingCode(TextAnimation.Wobbly);
|
||||||
|
FormattingCodes["typing"] = new FormattingCode(TextAnimation.Typing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetFormatIndicators(char opener, char closer) {
|
public static void SetFormatIndicators(char opener, char closer) {
|
||||||
|
@ -40,7 +48,10 @@ namespace MLEM.Formatting {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string RemoveFormatting(this string s) {
|
public static string RemoveFormatting(this string s) {
|
||||||
return formatRegex.Replace(s, match => FromMatch(match).GetReplacementString());
|
return formatRegex.Replace(s, match => {
|
||||||
|
var code = FromMatch(match);
|
||||||
|
return code != null ? code.GetReplacementString() : string.Empty;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<int, FormattingCode> GetFormattingCodes(this string s) {
|
public static Dictionary<int, FormattingCode> GetFormattingCodes(this string s) {
|
||||||
|
@ -48,50 +59,61 @@ namespace MLEM.Formatting {
|
||||||
var codeLengths = 0;
|
var codeLengths = 0;
|
||||||
foreach (Match match in formatRegex.Matches(s)) {
|
foreach (Match match in formatRegex.Matches(s)) {
|
||||||
var code = FromMatch(match);
|
var code = FromMatch(match);
|
||||||
|
if (code == null)
|
||||||
|
continue;
|
||||||
codes[match.Index - codeLengths] = code;
|
codes[match.Index - codeLengths] = code;
|
||||||
codeLengths += match.Length - code.GetReplacementString().Length;
|
codeLengths += match.Length - code.GetReplacementString().Length;
|
||||||
}
|
}
|
||||||
return codes;
|
return codes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawFormattedString(this IGenericFont regularFont, SpriteBatch batch, Vector2 pos, string text, Dictionary<int, FormattingCode> codeLocations, Color color, float scale, IGenericFont boldFont = null, IGenericFont italicFont = null, float depth = 0) {
|
public static void DrawFormattedString(this IGenericFont regularFont, SpriteBatch batch, Vector2 pos, string text, Dictionary<int, FormattingCode> codeLocations, Color color, float scale, IGenericFont boldFont = null, IGenericFont italicFont = null, float depth = 0, TimeSpan timeIntoAnimation = default) {
|
||||||
var characterCounter = 0;
|
|
||||||
var currColor = color;
|
var currColor = color;
|
||||||
var currFont = regularFont;
|
var currFont = regularFont;
|
||||||
|
var currAnim = TextAnimation.Default;
|
||||||
|
var animStart = 0;
|
||||||
|
|
||||||
var innerOffset = new Vector2();
|
var innerOffset = new Vector2();
|
||||||
foreach (var c in text) {
|
for (var i = 0; i < text.Length; i++) {
|
||||||
// check if the current character's index has a formatting code
|
// check if the current character's index has a formatting code
|
||||||
codeLocations.TryGetValue(characterCounter, out var code);
|
codeLocations.TryGetValue(i, out var code);
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
// if so, apply it
|
// if so, apply it
|
||||||
if (code.CodeType == FormattingCode.Type.Color) {
|
switch (code.CodeType) {
|
||||||
currColor = code.Color.CopyAlpha(color);
|
case FormattingCode.Type.Color:
|
||||||
} else if (code.CodeType == FormattingCode.Type.Style) {
|
currColor = code.Color.CopyAlpha(color);
|
||||||
switch (code.Style) {
|
break;
|
||||||
case TextStyle.Regular:
|
case FormattingCode.Type.Style:
|
||||||
currFont = regularFont;
|
switch (code.Style) {
|
||||||
break;
|
case TextStyle.Regular:
|
||||||
case TextStyle.Bold:
|
currFont = regularFont;
|
||||||
currFont = boldFont ?? regularFont;
|
break;
|
||||||
break;
|
case TextStyle.Bold:
|
||||||
case TextStyle.Italic:
|
currFont = boldFont ?? regularFont;
|
||||||
currFont = italicFont ?? regularFont;
|
break;
|
||||||
break;
|
case TextStyle.Italic:
|
||||||
}
|
currFont = italicFont ?? regularFont;
|
||||||
} else if (code.CodeType == FormattingCode.Type.Icon) {
|
break;
|
||||||
var iconSc = new Vector2(1F / code.Icon.Width, 1F / code.Icon.Height) * regularFont.LineHeight * scale;
|
}
|
||||||
batch.Draw(code.Icon, pos + innerOffset, color, 0, Vector2.Zero, iconSc, SpriteEffects.None, depth);
|
break;
|
||||||
|
case FormattingCode.Type.Icon:
|
||||||
|
var iconSc = new Vector2(1F / code.Icon.Width, 1F / code.Icon.Height) * regularFont.LineHeight * scale;
|
||||||
|
batch.Draw(code.Icon, pos + innerOffset, color, 0, Vector2.Zero, iconSc, SpriteEffects.None, depth);
|
||||||
|
break;
|
||||||
|
case FormattingCode.Type.Animation:
|
||||||
|
currAnim = code.Animation;
|
||||||
|
animStart = i;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
characterCounter++;
|
|
||||||
|
|
||||||
|
var c = text[i];
|
||||||
var cSt = c.ToString();
|
var cSt = c.ToString();
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
innerOffset.X = 0;
|
innerOffset.X = 0;
|
||||||
innerOffset.Y += regularFont.LineHeight * scale;
|
innerOffset.Y += regularFont.LineHeight * scale;
|
||||||
} else {
|
} else {
|
||||||
currFont.DrawString(batch, cSt, pos + innerOffset, currColor, 0, Vector2.Zero, scale, SpriteEffects.None, depth);
|
currAnim(currFont, batch, text, i, animStart, cSt, pos + innerOffset, currColor, scale, depth, timeIntoAnimation);
|
||||||
// we measure the string with the regular font here so that previously split
|
// we measure the string with the regular font here so that previously split
|
||||||
// strings don't get too long with a bolder font. This shouldn't effect visuals too much
|
// strings don't get too long with a bolder font. This shouldn't effect visuals too much
|
||||||
innerOffset.X += regularFont.MeasureString(cSt).X * scale;
|
innerOffset.X += regularFont.MeasureString(cSt).X * scale;
|
||||||
|
@ -101,7 +123,8 @@ namespace MLEM.Formatting {
|
||||||
|
|
||||||
private static FormattingCode FromMatch(Capture match) {
|
private static FormattingCode FromMatch(Capture match) {
|
||||||
var rawCode = match.Value.Substring(1, match.Value.Length - 2).ToLowerInvariant();
|
var rawCode = match.Value.Substring(1, match.Value.Length - 2).ToLowerInvariant();
|
||||||
return FormattingCodes[rawCode];
|
FormattingCodes.TryGetValue(rawCode, out var val);
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue