1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-12-25 17:59:24 +01:00

Revert "part 2: format state and making the codes do the work"

This reverts commit 02b25236
This commit is contained in:
Ellpeck 2020-02-03 04:36:49 +01:00
parent 02b25236b1
commit d78448a4ed
4 changed files with 82 additions and 134 deletions

View file

@ -1,14 +1,28 @@
using System; using System;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Font;
namespace MLEM.Formatting { namespace MLEM.Formatting {
public class AnimationCode : FormattingCode { public class AnimationCode : FormattingCode {
public readonly FormatState.DrawCharacter Draw; public static readonly DrawCharacter Default = (code, settings, font, batch, totalText, index, effectStartIndex, charSt, position, color, scale, layerDepth) => {
font.DrawString(batch, charSt, position, color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
};
public static readonly DrawCharacter Wobbly = (code, settings, font, batch, totalText, index, effectStartIndex, charSt, position, color, scale, layerDepth) => {
var offset = new Vector2(0, (float) Math.Sin(index + code.Time.TotalSeconds * settings.WobbleModifier) * font.LineHeight * settings.WobbleHeightModifier * scale);
font.DrawString(batch, charSt, position + offset, color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
};
public static readonly DrawCharacter Typing = (code, settings, font, batch, totalText, index, effectStartIndex, charSt, position, color, scale, layerDepth) => {
if (code.Time.TotalSeconds * settings.TypingSpeed > index - effectStartIndex + 1)
font.DrawString(batch, charSt, position, color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
};
public static readonly AnimationCode DefaultCode = new AnimationCode(Default);
public readonly DrawCharacter Draw;
public TimeSpan Time; public TimeSpan Time;
public AnimationCode(int startIndex, FormatState.DrawCharacter draw) : base(startIndex, Type.Animation) { public AnimationCode(DrawCharacter draw) : base(Type.Animation) {
this.Draw = draw; this.Draw = draw;
} }
@ -20,9 +34,7 @@ namespace MLEM.Formatting {
this.Time = TimeSpan.Zero; this.Time = TimeSpan.Zero;
} }
public override void ModifyFormatting(ref FormatState state) { public delegate void DrawCharacter(AnimationCode code, FormatSettings settings, IGenericFont font, SpriteBatch batch, string totalText, int index, int effectStartIndex, string charSt, Vector2 position, Color color, float scale, float layerDepth);
state.DrawBehavior = this.Draw;
}
} }
} }

View file

@ -1,30 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Font;
namespace MLEM.Formatting {
public struct FormatState {
public static readonly DrawCharacter DefaultDrawBehavior = (state, batch, totalText, index, charSt, position, scale, layerDepth) => {
state.Font.DrawString(batch, charSt, position, state.Color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
};
public FormattingCodeCollection FormattingCodes { get; internal set; }
public IGenericFont RegularFont { get; internal set; }
public IGenericFont ItalicFont { get; internal set; }
public IGenericFont BoldFont { get; internal set; }
public FormatSettings Settings { get; internal set; }
public int CurrentIndex { get; internal set; }
public Vector2 InnerOffset { get; internal set; }
public Color Color;
public IGenericFont Font;
public DrawCharacter DrawBehavior;
public void PrependBehavior(DrawCharacter behavior) {
this.DrawBehavior = behavior + this.DrawBehavior;
}
public delegate void DrawCharacter(FormatState state, SpriteBatch batch, string totalText, int index, string charSt, Vector2 position, float scale, float layerDepth);
}
}

View file

@ -1,9 +1,6 @@
using System;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Animations; using MLEM.Animations;
using MLEM.Font; using MLEM.Font;
using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
namespace MLEM.Formatting { namespace MLEM.Formatting {
@ -13,26 +10,24 @@ namespace MLEM.Formatting {
public readonly Color Color; public readonly Color Color;
public readonly TextStyle Style; public readonly TextStyle Style;
public readonly SpriteAnimation Icon; public readonly SpriteAnimation Icon;
public readonly int StartIndex;
protected FormattingCode(int startIndex, Type type) { protected FormattingCode(Type type) {
this.CodeType = type; this.CodeType = type;
this.StartIndex = startIndex;
} }
public FormattingCode(int startIndex, Color color) : this(startIndex, Type.Color) { public FormattingCode(Color color) : this(Type.Color) {
this.Color = color; this.Color = color;
} }
public FormattingCode(int startIndex, TextStyle style) : this(startIndex, Type.Style) { public FormattingCode(TextStyle style) : this(Type.Style) {
this.Style = style; this.Style = style;
} }
public FormattingCode(int startIndex, TextureRegion icon) : public FormattingCode(TextureRegion icon) :
this(startIndex, new SpriteAnimation(0, icon)) { this(new SpriteAnimation(0, icon)) {
} }
public FormattingCode(int startIndex, SpriteAnimation icon) : this(startIndex, Type.Icon) { public FormattingCode(SpriteAnimation icon) : this(Type.Icon) {
this.Icon = icon; this.Icon = icon;
} }
@ -50,46 +45,6 @@ namespace MLEM.Formatting {
this.Icon.Restart(); this.Icon.Restart();
} }
public virtual void ModifyFormatting(ref FormatState state) {
switch (this.CodeType) {
case Type.Color:
state.Color = this.Color;
break;
case Type.Style:
switch (this.Style) {
case TextStyle.Regular:
state.DrawBehavior = FormatState.DefaultDrawBehavior;
state.Font = state.RegularFont;
break;
case TextStyle.Bold:
state.Font = state.BoldFont;
break;
case TextStyle.Italic:
state.Font = state.ItalicFont;
break;
case TextStyle.Shadow:
var formatState = state;
state.PrependBehavior((s, batch, totalText, index, charSt, position, scale, layerDepth) => {
var lastColor = s.Color;
s.Color = s.Settings.DropShadowColor;
// Call the last behavior to draw the shadow
formatState.DrawBehavior(s, batch, totalText, index, charSt, position + s.Settings.DropShadowOffset * scale, scale, layerDepth);
s.Color = lastColor;
});
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
case Type.Icon:
state.PrependBehavior((s, batch, totalText, index, charSt, position, scale, layerDepth) => {
if (index == this.StartIndex)
batch.Draw(this.Icon.CurrentRegion, new RectangleF(position, new Vector2(s.RegularFont.LineHeight * scale)), s.Color, 0, Vector2.Zero, SpriteEffects.None, layerDepth);
});
break;
}
}
public enum Type { public enum Type {
Color, Color,

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Animations;
using MLEM.Extensions; using MLEM.Extensions;
using MLEM.Font; using MLEM.Font;
using MLEM.Misc; using MLEM.Misc;
@ -12,7 +11,7 @@ using MLEM.Textures;
namespace MLEM.Formatting { namespace MLEM.Formatting {
public static class TextFormatting { public static class TextFormatting {
public static readonly Dictionary<Regex, Func<Match, int, FormattingCode>> FormattingCodes = new Dictionary<Regex, Func<Match, int, FormattingCode>>(); public static readonly Dictionary<Regex, Func<Match, FormattingCode>> FormattingCodes = new Dictionary<Regex, Func<Match, FormattingCode>>();
private static readonly Dictionary<IGenericFont, string> OneEmStrings = new Dictionary<IGenericFont, string>(); private static readonly Dictionary<IGenericFont, string> OneEmStrings = new Dictionary<IGenericFont, string>();
private static Regex formatRegex; private static Regex formatRegex;
@ -20,30 +19,22 @@ namespace MLEM.Formatting {
SetFormatIndicators('[', ']'); SetFormatIndicators('[', ']');
// style codes // style codes
FormattingCodes[new Regex("regular")] = (m, i) => new FormattingCode(i, TextStyle.Regular); FormattingCodes[new Regex("regular")] = m => new FormattingCode(TextStyle.Regular);
FormattingCodes[new Regex("italic")] = (m, i) => new FormattingCode(i, TextStyle.Italic); FormattingCodes[new Regex("italic")] = m => new FormattingCode(TextStyle.Italic);
FormattingCodes[new Regex("bold")] = (m, i) => new FormattingCode(i, TextStyle.Bold); FormattingCodes[new Regex("bold")] = m => new FormattingCode(TextStyle.Bold);
FormattingCodes[new Regex("shadow")] = (m, i) => new FormattingCode(i, TextStyle.Shadow); FormattingCodes[new Regex("shadow")] = m => new FormattingCode(TextStyle.Shadow);
// color codes // 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[new Regex(color.Name.ToLowerInvariant())] = (m, i) => new FormattingCode(i, (Color) color.GetValue(null)); FormattingCodes[new Regex(color.Name.ToLowerInvariant())] = m => new FormattingCode((Color) color.GetValue(null));
} }
// animations // animations
FormattingCodes[new Regex("unanimated")] = (m, i) => new AnimationCode(i, FormatState.DefaultDrawBehavior); FormattingCodes[new Regex("unanimated")] = m => new AnimationCode(AnimationCode.Default);
FormattingCodes[new Regex("wobbly")] = (m, i) => new AnimationCode(i, (state, batch, totalText, index, charSt, position, scale, layerDepth) => { FormattingCodes[new Regex("wobbly")] = m => new AnimationCode(AnimationCode.Wobbly);
var code = (AnimationCode) state.FormattingCodes[i]; FormattingCodes[new Regex("typing")] = m => new AnimationCode(AnimationCode.Typing);
var offset = new Vector2(0, (float) Math.Sin(index + code.Time.TotalSeconds * state.Settings.WobbleModifier) * state.Font.LineHeight * state.Settings.WobbleHeightModifier * scale);
state.Font.DrawString(batch, charSt, position + offset, state.Color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
});
FormattingCodes[new Regex("typing")] = (m, i) => new AnimationCode(i, (state, batch, totalText, index, charSt, position, scale, layerDepth) => {
var code = (AnimationCode) state.FormattingCodes[i];
if (code.Time.TotalSeconds * state.Settings.TypingSpeed > index - i + 1)
state.Font.DrawString(batch, charSt, position, state.Color, 0, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
});
} }
public static void SetFormatIndicators(char opener, char closer) { public static void SetFormatIndicators(char opener, char closer) {
@ -65,15 +56,9 @@ namespace MLEM.Formatting {
} }
public static string RemoveFormatting(this string s, IGenericFont font) { public static string RemoveFormatting(this string s, IGenericFont font) {
var codeLengths = 0;
return formatRegex.Replace(s, match => { return formatRegex.Replace(s, match => {
var code = FromMatch(match, match.Index - codeLengths); var code = FromMatch(match);
if (code != null) { return code != null ? code.GetReplacementString(font) : string.Empty;
var replace = code.GetReplacementString(font);
codeLengths += match.Length - replace.Length;
return replace;
}
return match.Value;
}); });
} }
@ -81,51 +66,77 @@ namespace MLEM.Formatting {
var codes = new FormattingCodeCollection(); var codes = new FormattingCodeCollection();
var codeLengths = 0; var codeLengths = 0;
foreach (Match match in formatRegex.Matches(s)) { foreach (Match match in formatRegex.Matches(s)) {
var index = match.Index - codeLengths; var code = FromMatch(match);
var code = FromMatch(match, index);
if (code == null) if (code == null)
continue; continue;
codes[index] = code; codes[match.Index - codeLengths] = code;
codeLengths += match.Length - code.GetReplacementString(font).Length; codeLengths += match.Length - code.GetReplacementString(font).Length;
} }
return codes; return codes;
} }
public static void DrawFormattedString(this IGenericFont regularFont, SpriteBatch batch, Vector2 pos, string text, FormattingCodeCollection codes, Color color, float scale, IGenericFont boldFont = null, IGenericFont italicFont = null, float depth = 0, FormatSettings formatSettings = null) { public static void DrawFormattedString(this IGenericFont regularFont, SpriteBatch batch, Vector2 pos, string text, FormattingCodeCollection codes, Color color, float scale, IGenericFont boldFont = null, IGenericFont italicFont = null, float depth = 0, FormatSettings formatSettings = null) {
var state = new FormatState { var settings = formatSettings ?? FormatSettings.Default;
FormattingCodes = codes, var currColor = color;
RegularFont = regularFont, var currFont = regularFont;
ItalicFont = italicFont, var currStyle = TextStyle.Regular;
BoldFont = boldFont, var currAnim = AnimationCode.DefaultCode;
Settings = formatSettings ?? FormatSettings.Default, var animStart = 0;
Color = color,
Font = regularFont,
DrawBehavior = FormatState.DefaultDrawBehavior
};
var innerOffset = new Vector2();
for (var i = 0; i < text.Length; i++) { for (var i = 0; i < text.Length; i++) {
state.CurrentIndex = i; // check if the current character's index has a formatting code
if (codes.TryGetValue(i, out var code)) codes.TryGetValue(i, out var code);
code.ModifyFormatting(ref state); if (code != null) {
// if so, apply it
switch (code.CodeType) {
case FormattingCode.Type.Color:
currColor = code.Color.CopyAlpha(color);
break;
case FormattingCode.Type.Style:
switch (code.Style) {
case TextStyle.Regular:
currFont = regularFont;
break;
case TextStyle.Bold:
currFont = boldFont ?? regularFont;
break;
case TextStyle.Italic:
currFont = italicFont ?? regularFont;
break;
}
currStyle = code.Style;
break;
case FormattingCode.Type.Icon:
batch.Draw(code.Icon.CurrentRegion, new RectangleF(pos + innerOffset, new Vector2(regularFont.LineHeight * scale)), color, 0, Vector2.Zero, SpriteEffects.None, depth);
break;
case FormattingCode.Type.Animation:
currAnim = (AnimationCode) code;
animStart = i;
break;
}
}
var c = text[i]; var c = text[i];
var cSt = c.ToString(); var cSt = c.ToString();
if (c == '\n') { if (c == '\n') {
state.InnerOffset = new Vector2(0, state.InnerOffset.Y + regularFont.LineHeight * scale); innerOffset.X = 0;
innerOffset.Y += regularFont.LineHeight * scale;
} else { } else {
state.DrawBehavior(state, batch, text, i, cSt, pos + state.InnerOffset, scale, depth); if (currStyle == TextStyle.Shadow)
state.InnerOffset += new Vector2(regularFont.MeasureString(cSt).X * scale, 0); currAnim.Draw(currAnim, settings, currFont, batch, text, i, animStart, cSt, pos + innerOffset + settings.DropShadowOffset * scale, settings.DropShadowColor, scale, depth);
currAnim.Draw(currAnim, settings, currFont, batch, text, i, animStart, cSt, pos + innerOffset, currColor, scale, depth);
innerOffset.X += regularFont.MeasureString(cSt).X * scale;
} }
} }
} }
private static FormattingCode FromMatch(Capture match, int index) { 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();
foreach (var code in FormattingCodes) { foreach (var code in FormattingCodes) {
var m = code.Key.Match(rawCode); var m = code.Key.Match(rawCode);
if (m.Success) if (m.Success)
return code.Value(m, index); return code.Value(m);
} }
return null; return null;
} }