1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-22 04:53:29 +01:00

Added the ability for formatted (tokenized) strings to be drawn with custom rotation, origin and flipping

Closes #18
This commit is contained in:
Ell 2024-04-10 20:27:00 +02:00
parent e00769a4ed
commit 9a03a8c62d
19 changed files with 148 additions and 120 deletions

View file

@ -2,7 +2,7 @@
MLEM tries to adhere to [semantic versioning](https://semver.org/). Potentially breaking changes are written in **bold**. MLEM tries to adhere to [semantic versioning](https://semver.org/). Potentially breaking changes are written in **bold**.
Jump to version: Jump to version:
- [6.3.2](#632-in-development) - [7.0.0](#700-in-development)
- [6.3.1](#631) - [6.3.1](#631)
- [6.3.0](#630) - [6.3.0](#630)
- [6.2.0](#620) - [6.2.0](#620)
@ -13,7 +13,11 @@ Jump to version:
- [5.1.0](#510) - [5.1.0](#510)
- [5.0.0](#500) - [5.0.0](#500)
## 6.3.2 (In Development) ## 7.0.0 (In Development)
### MLEM
Additions
- **Added the ability for formatted (tokenized) strings to be drawn with custom rotation, origin and flipping**
### MLEM.Ui ### MLEM.Ui
Additions Additions

View file

@ -27,6 +27,7 @@ namespace Demos {
private TokenizedString tokenizedText; private TokenizedString tokenizedText;
private GenericFont font; private GenericFont font;
private bool drawBounds; private bool drawBounds;
private bool transform;
private float Scale { private float Scale {
get { get {
// calculate our scale based on how much larger the window is, so that the text scales with the window // calculate our scale based on how much larger the window is, so that the text scales with the window
@ -85,7 +86,11 @@ namespace Demos {
} }
// draw the text itself (start and end indices are optional) // draw the text itself (start and end indices are optional)
this.tokenizedText.Draw(time, this.SpriteBatch, pos, this.font, Color.White, this.Scale, 0, this.startIndex, this.endIndex); this.tokenizedText.Draw(time, this.SpriteBatch, pos, this.font, Color.White, this.Scale, 0,
this.transform ? 0.25F : 0,
this.transform ? new Vector2(size.X / this.Scale, 128) : Vector2.Zero,
this.transform ? SpriteEffects.FlipHorizontally : SpriteEffects.None,
this.startIndex, this.endIndex);
this.SpriteBatch.End(); this.SpriteBatch.End();
} }
@ -97,6 +102,8 @@ namespace Demos {
// change some demo showcase info based on keybinds // change some demo showcase info based on keybinds
if (this.InputHandler.IsPressed(Keys.B)) if (this.InputHandler.IsPressed(Keys.B))
this.drawBounds = !this.drawBounds; this.drawBounds = !this.drawBounds;
if (this.InputHandler.IsPressed(Keys.T))
this.transform = !this.transform;
if (this.startIndex > 0 && this.InputHandler.IsDown(Keys.Left)) if (this.startIndex > 0 && this.InputHandler.IsDown(Keys.Left))
this.startIndex--; this.startIndex--;
if (this.startIndex < this.tokenizedText.String.Length && this.InputHandler.IsDown(Keys.Right)) if (this.startIndex < this.tokenizedText.String.Length && this.InputHandler.IsDown(Keys.Right))

View file

@ -38,7 +38,7 @@ namespace MLEM.Extended.Font {
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth) { public override void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth) {
batch.DrawString(this.Font, character, position, color, rotation, Vector2.Zero, scale, effects, layerDepth); batch.DrawString(this.Font, character, position, color, rotation, Vector2.Zero, scale, effects, layerDepth);
} }

View file

@ -47,7 +47,7 @@ namespace MLEM.Extended.Font {
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth) { public override void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth) {
this.Font.DrawText(batch, character, position, color, rotation, Vector2.Zero, scale, layerDepth, this.CharacterSpacing, this.LineSpacing); this.Font.DrawText(batch, character, position, color, rotation, Vector2.Zero, scale, layerDepth, this.CharacterSpacing, this.LineSpacing);
} }

View file

@ -246,7 +246,7 @@ namespace MLEM.Ui.Elements {
var pos = this.DisplayArea.Location + new Vector2(this.GetAlignmentOffset(), 0); var pos = this.DisplayArea.Location + new Vector2(this.GetAlignmentOffset(), 0);
var sc = this.TextScale * this.TextScaleMultiplier * this.Scale; var sc = this.TextScale * this.TextScaleMultiplier * this.Scale;
var color = this.TextColor.OrDefault(Color.White) * alpha; var color = this.TextColor.OrDefault(Color.White) * alpha;
this.TokenizedText.Draw(time, batch, pos, this.RegularFont, color, sc, 0, this.DrawStartIndex, this.DrawEndIndex); this.TokenizedText.Draw(time, batch, pos, this.RegularFont, color, sc, 0, 0, Vector2.Zero, SpriteEffects.None, this.DrawStartIndex, this.DrawEndIndex);
base.Draw(time, batch, alpha, context); base.Draw(time, batch, alpha, context);
} }

View file

@ -4,6 +4,8 @@ using System.Linq;
using System.Text; using System.Text;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Formatting;
using MLEM.Formatting.Codes;
using MLEM.Misc; using MLEM.Misc;
namespace MLEM.Font { namespace MLEM.Font {
@ -59,7 +61,7 @@ namespace MLEM.Font {
/// <summary> /// <summary>
/// Draws the given code point with the given data for use in <see cref="DrawString(Microsoft.Xna.Framework.Graphics.SpriteBatch,System.Text.StringBuilder,Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Color,float,Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Graphics.SpriteEffects,float)"/>. /// Draws the given code point with the given data for use in <see cref="DrawString(Microsoft.Xna.Framework.Graphics.SpriteBatch,System.Text.StringBuilder,Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Color,float,Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Graphics.SpriteEffects,float)"/>.
/// Note that this method is only called internally. /// Note that this method should only be called internally for rendering of more complex strings, like in <see cref="TextFormatter"/> <see cref="Code"/> implementations.
/// </summary> /// </summary>
/// <param name="batch">The sprite batch to draw with.</param> /// <param name="batch">The sprite batch to draw with.</param>
/// <param name="codePoint">The code point which will be drawn.</param> /// <param name="codePoint">The code point which will be drawn.</param>
@ -70,7 +72,7 @@ namespace MLEM.Font {
/// <param name="scale">A scaling of this character.</param> /// <param name="scale">A scaling of this character.</param>
/// <param name="effects">Modificators for drawing. Can be combined.</param> /// <param name="effects">Modificators for drawing. Can be combined.</param>
/// <param name="layerDepth">A depth of the layer of this character.</param> /// <param name="layerDepth">A depth of the layer of this character.</param>
protected abstract void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth); public abstract void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth);
///<inheritdoc cref="SpriteBatch.DrawString(SpriteFont,string,Vector2,Color,float,Vector2,float,SpriteEffects,float)"/> ///<inheritdoc cref="SpriteBatch.DrawString(SpriteFont,string,Vector2,Color,float,Vector2,float,SpriteEffects,float)"/>
public void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) { public void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
@ -174,6 +176,52 @@ namespace MLEM.Font {
return GenericFont.SplitStringSeparate(Enumerable.Repeat(new DecoratedCodePointSource(new CodePointSource(text), this, 0), 1), width, scale).First(); return GenericFont.SplitStringSeparate(Enumerable.Repeat(new DecoratedCodePointSource(new CodePointSource(text), this, 0), 1), width, scale).First();
} }
public Matrix CalculateStringTransform(Vector2 position, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Vector2 flipSize) {
var (flipX, flipY) = (0F, 0F);
var flippedV = (effects & SpriteEffects.FlipVertically) != 0;
var flippedH = (effects & SpriteEffects.FlipHorizontally) != 0;
if (flippedV || flippedH) {
if (flippedH) {
origin.X *= -1;
flipX = -flipSize.X;
}
if (flippedV) {
origin.Y *= -1;
flipY = this.LineHeight - flipSize.Y;
}
}
var trans = Matrix.Identity;
if (rotation == 0) {
trans.M11 = flippedH ? -scale.X : scale.X;
trans.M22 = flippedV ? -scale.Y : scale.Y;
trans.M41 = (flipX - origin.X) * trans.M11 + position.X;
trans.M42 = (flipY - origin.Y) * trans.M22 + position.Y;
} else {
var sin = (float) Math.Sin(rotation);
var cos = (float) Math.Cos(rotation);
trans.M11 = (flippedH ? -scale.X : scale.X) * cos;
trans.M12 = (flippedH ? -scale.X : scale.X) * sin;
trans.M21 = (flippedV ? -scale.Y : scale.Y) * -sin;
trans.M22 = (flippedV ? -scale.Y : scale.Y) * cos;
trans.M41 = (flipX - origin.X) * trans.M11 + (flipY - origin.Y) * trans.M21 + position.X;
trans.M42 = (flipX - origin.X) * trans.M12 + (flipY - origin.Y) * trans.M22 + position.Y;
}
return trans;
}
public Vector2 MoveFlipped(Vector2 charPos, SpriteEffects effects, Vector2 charSize) {
if ((effects & SpriteEffects.FlipHorizontally) != 0)
charPos.X += charSize.X;
if ((effects & SpriteEffects.FlipVertically) != 0)
charPos.Y += charSize.Y - this.LineHeight;
return charPos;
}
public Vector2 TransformSingleCharacter(Vector2 stringPos, Vector2 charPosOffset, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
return Vector2.Transform(this.MoveFlipped(charPosOffset, effects, charSize), this.CalculateStringTransform(stringPos, rotation, origin, scale, effects, stringSize));
}
private Vector2 MeasureString(CodePointSource text, bool ignoreTrailingSpaces) { private Vector2 MeasureString(CodePointSource text, bool ignoreTrailingSpaces) {
var size = Vector2.Zero; var size = Vector2.Zero;
if (text.Length <= 0) if (text.Length <= 0)
@ -220,7 +268,7 @@ namespace MLEM.Font {
private void DrawString(SpriteBatch batch, CodePointSource text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) { private void DrawString(SpriteBatch batch, CodePointSource text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
var flipSize = effects != SpriteEffects.None ? this.MeasureString(text, false) : Vector2.Zero; var flipSize = effects != SpriteEffects.None ? this.MeasureString(text, false) : Vector2.Zero;
var trans = this.CalculateStringTransform(position, rotation, origin, scale, flipSize, effects); var trans = this.CalculateStringTransform(position, rotation, origin, scale, effects, flipSize);
var offset = Vector2.Zero; var offset = Vector2.Zero;
var index = 0; var index = 0;
@ -232,14 +280,7 @@ namespace MLEM.Font {
} else { } else {
var character = CodePointSource.ToString(codePoint); var character = CodePointSource.ToString(codePoint);
var charSize = this.MeasureString(character); var charSize = this.MeasureString(character);
var charPos = Vector2.Transform(this.MoveFlipped(offset, effects, charSize), trans);
var charPos = offset;
if ((effects & SpriteEffects.FlipHorizontally) != 0)
charPos.X += charSize.X;
if ((effects & SpriteEffects.FlipVertically) != 0)
charPos.Y += charSize.Y - this.LineHeight;
charPos = Vector2.Transform(charPos, trans);
this.DrawCharacter(batch, codePoint, character, charPos, color, rotation, scale, effects, layerDepth); this.DrawCharacter(batch, codePoint, character, charPos, color, rotation, scale, effects, layerDepth);
offset.X += charSize.X; offset.X += charSize.X;
} }
@ -367,40 +408,6 @@ namespace MLEM.Font {
} }
} }
internal Matrix CalculateStringTransform(Vector2 position, float rotation, Vector2 origin, Vector2 scale, Vector2 flipSize, SpriteEffects effects) {
var (flipX, flipY) = (0F, 0F);
var flippedV = (effects & SpriteEffects.FlipVertically) != 0;
var flippedH = (effects & SpriteEffects.FlipHorizontally) != 0;
if (flippedV || flippedH) {
if (flippedH) {
origin.X *= -1;
flipX = -flipSize.X;
}
if (flippedV) {
origin.Y *= -1;
flipY = this.LineHeight - flipSize.Y;
}
}
var trans = Matrix.Identity;
if (rotation == 0) {
trans.M11 = flippedH ? -scale.X : scale.X;
trans.M22 = flippedV ? -scale.Y : scale.Y;
trans.M41 = (flipX - origin.X) * trans.M11 + position.X;
trans.M42 = (flipY - origin.Y) * trans.M22 + position.Y;
} else {
var sin = (float) Math.Sin(rotation);
var cos = (float) Math.Cos(rotation);
trans.M11 = (flippedH ? -scale.X : scale.X) * cos;
trans.M12 = (flippedH ? -scale.X : scale.X) * sin;
trans.M21 = (flippedV ? -scale.Y : scale.Y) * -sin;
trans.M22 = (flippedV ? -scale.Y : scale.Y) * cos;
trans.M41 = (flipX - origin.X) * trans.M11 + (flipY - origin.Y) * trans.M21 + position.X;
trans.M42 = (flipX - origin.X) * trans.M12 + (flipY - origin.Y) * trans.M22 + position.Y;
}
return trans;
}
private static bool IsTrailingSpace(CodePointSource s, int index) { private static bool IsTrailingSpace(CodePointSource s, int index) {
while (index < s.Length) { while (index < s.Length) {
var (codePoint, length) = s.GetCodePoint(index); var (codePoint, length) = s.GetCodePoint(index);

View file

@ -39,7 +39,7 @@ namespace MLEM.Font {
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth) { public override void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth) {
batch.DrawString(this.Font, character, position, color, rotation, Vector2.Zero, scale, effects, layerDepth); batch.DrawString(this.Font, character, position, color, rotation, Vector2.Zero, scale, effects, layerDepth);
} }

View file

@ -92,12 +92,12 @@ namespace MLEM.Formatting.Codes {
} }
/// <inheritdoc cref="Formatting.Token.DrawCharacter"/> /// <inheritdoc cref="Formatting.Token.DrawCharacter"/>
public virtual 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) { public virtual bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
return false; return false;
} }
/// <inheritdoc cref="Formatting.Token.DrawSelf"/> /// <inheritdoc cref="Formatting.Token.DrawSelf"/>
public virtual void DrawSelf(GameTime time, SpriteBatch batch, Token token, Vector2 pos, GenericFont font, Color color, float scale, float depth) {} public virtual void DrawSelf(GameTime time, SpriteBatch batch, Token token, Vector2 stringPos, Vector2 charPosOffset, GenericFont font, Color color, Vector2 scale, float rotation, Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize) {}
/// <summary> /// <summary>
/// Creates a new formatting code from the given regex and regex match. /// Creates a new formatting code from the given regex and regex match.

View file

@ -36,9 +36,11 @@ namespace MLEM.Formatting.Codes {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void DrawSelf(GameTime time, SpriteBatch batch, Token token, Vector2 pos, GenericFont font, Color color, float scale, float depth) { public override void DrawSelf(GameTime time, SpriteBatch batch, Token token, Vector2 stringPos, Vector2 charPosOffset, GenericFont font, Color color, Vector2 scale, float rotation, Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize) {
var actualColor = this.copyTextColor ? color : Color.White.CopyAlpha(color); var actualColor = this.copyTextColor ? color : Color.White.CopyAlpha(color);
batch.Draw(this.image.CurrentRegion, new RectangleF(pos, new Vector2(font.LineHeight * scale)), actualColor); var size = new Vector2(font.LineHeight);
var finalPos = font.TransformSingleCharacter(stringPos, charPosOffset, rotation, origin, scale, effects, stringSize, size);
batch.Draw(this.image.CurrentRegion, new RectangleF(finalPos, size * scale), actualColor, rotation, Vector2.Zero, effects, 0);
} }
} }

View file

@ -40,9 +40,9 @@ namespace MLEM.Formatting.Codes {
} }
/// <inheritdoc /> /// <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) { public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
// since we inherit from UnderlineCode, we can just call base if selected // since we inherit from UnderlineCode, we can just call base if selected
return this.IsSelected() && base.DrawCharacter(time, batch, codePoint, character, token, indexInToken, ref pos, font, ref color, ref scale, depth); return this.IsSelected() && base.DrawCharacter(time, batch, codePoint, character, token, indexInToken, stringPos, ref charPosOffset, font, ref color, ref scale, ref rotation, ref origin, depth, effects, stringPos, charSize);
} }
} }

View file

@ -22,10 +22,11 @@ namespace MLEM.Formatting.Codes {
} }
/// <inheritdoc /> /// <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) { public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
foreach (var dir in this.diagonals ? Direction2Helper.AllExceptNone : Direction2Helper.Adjacent) { foreach (var dir in this.diagonals ? Direction2Helper.AllExceptNone : Direction2Helper.Adjacent) {
var offset = Vector2.Normalize(dir.Offset().ToVector2()) * (this.thickness * scale); var offset = Vector2.Normalize(dir.Offset().ToVector2()) * this.thickness;
font.DrawString(batch, character, pos + offset, this.color.CopyAlpha(color), 0, Vector2.Zero, scale, SpriteEffects.None, depth); var finalPos = font.TransformSingleCharacter(stringPos, charPosOffset + offset, rotation, origin, scale, effects, stringSize, charSize);
font.DrawString(batch, character, finalPos, this.color.CopyAlpha(color), rotation, Vector2.Zero, scale, effects, depth);
} }
return false; return false;
} }

View file

@ -18,8 +18,9 @@ namespace MLEM.Formatting.Codes {
} }
/// <inheritdoc /> /// <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) { public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
font.DrawString(batch, character, pos + this.offset * scale, this.color.CopyAlpha(color), 0, Vector2.Zero, scale, SpriteEffects.None, depth); var finalPos = font.TransformSingleCharacter(stringPos, charPosOffset + this.offset, rotation, origin, scale, effects, stringSize, charSize);
font.DrawString(batch, character, finalPos, this.color.CopyAlpha(color), rotation, Vector2.Zero, scale, effects, depth);
// we return false since we still want regular drawing to occur // we return false since we still want regular drawing to occur
return false; return false;
} }

View file

@ -15,8 +15,8 @@ namespace MLEM.Formatting.Codes {
} }
/// <inheritdoc /> /// <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) { public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
pos.Y += this.offset * font.LineHeight * scale; charPosOffset.Y += this.offset * font.LineHeight * scale.Y;
return false; return false;
} }

View file

@ -19,13 +19,12 @@ namespace MLEM.Formatting.Codes {
} }
/// <inheritdoc /> /// <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) { public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
// don't underline spaces at the end of lines // don't underline spaces at the end of lines
if (codePoint == ' ' && token.DisplayString.Length > indexInToken + 1 && token.DisplayString[indexInToken + 1] == '\n') if (codePoint == ' ' && token.DisplayString.Length > indexInToken + 1 && token.DisplayString[indexInToken + 1] == '\n')
return false; return false;
var size = font.MeasureString(character) * scale; var finalPos = font.TransformSingleCharacter(stringPos, charPosOffset + new Vector2(0, (this.yOffset - this.thickness) * charSize.Y), rotation, origin, scale, effects, stringSize, charSize);
var t = size.Y * this.thickness; batch.Draw(batch.GetBlankTexture(), new RectangleF(finalPos.X, finalPos.Y, charSize.X * scale.X, this.thickness * charSize.Y * scale.Y), null, color, rotation, Vector2.Zero, SpriteEffects.None, depth);
batch.Draw(batch.GetBlankTexture(), new RectangleF(pos.X, pos.Y + this.yOffset * size.Y - t, size.X, t), color);
return false; return false;
} }

View file

@ -28,9 +28,8 @@ namespace MLEM.Formatting.Codes {
} }
/// <inheritdoc /> /// <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) { public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
var offset = new Vector2(0, (float) Math.Sin(token.Index + indexInToken + this.TimeIntoAnimation.TotalSeconds * this.modifier) * font.LineHeight * this.heightModifier * scale); charPosOffset += new Vector2(0, (float) Math.Sin(token.Index + indexInToken + this.TimeIntoAnimation.TotalSeconds * this.modifier) * font.LineHeight * this.heightModifier * scale.Y);
pos += offset;
// we return false since we still want regular drawing to occur, we just changed the position // we return false since we still want regular drawing to occur, we just changed the position
return false; return false;
} }

View file

@ -109,9 +109,9 @@ namespace MLEM.Formatting {
/// <param name="color">The color to draw with</param> /// <param name="color">The color to draw with</param>
/// <param name="scale">The scale to draw at</param> /// <param name="scale">The scale to draw at</param>
/// <param name="depth">The depth to draw at</param> /// <param name="depth">The depth to draw at</param>
public void DrawSelf(GameTime time, SpriteBatch batch, Vector2 pos, GenericFont font, Color color, float scale, float depth) { public void DrawSelf(GameTime time, SpriteBatch batch, Vector2 stringPos, Vector2 charPosOffset, GenericFont font, Color color, Vector2 scale, float rotation, Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize) {
foreach (var code in this.AppliedCodes) foreach (var code in this.AppliedCodes)
code.DrawSelf(time, batch, this, pos, font, color, scale, depth); code.DrawSelf(time, batch, this, stringPos, charPosOffset, font, color, scale, rotation, origin, depth, effects, stringSize);
} }
/// <summary> /// <summary>
@ -127,14 +127,15 @@ namespace MLEM.Formatting {
/// <param name="color">The color to draw with</param> /// <param name="color">The color to draw with</param>
/// <param name="scale">The scale to draw at</param> /// <param name="scale">The scale to draw at</param>
/// <param name="depth">The depth to draw at</param> /// <param name="depth">The depth to draw at</param>
public void DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, int indexInToken, Vector2 pos, GenericFont font, Color color, float scale, float depth) { public void DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, int indexInToken, Vector2 stringPos, Vector2 charPosOffset, GenericFont font, Color color, Vector2 scale, float rotation, Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
foreach (var code in this.AppliedCodes) { foreach (var code in this.AppliedCodes) {
if (code.DrawCharacter(time, batch, codePoint, character, this, indexInToken, ref pos, font, ref color, ref scale, depth)) if (code.DrawCharacter(time, batch, codePoint, character, this, indexInToken, stringPos, ref charPosOffset, font, ref color, ref scale, ref rotation, ref origin, depth, effects, stringSize, charSize))
return; return;
} }
// if no code drew, we have to do it ourselves // if no code drew, we have to do it ourselves
font.DrawString(batch, character, pos, color, 0, Vector2.Zero, scale, SpriteEffects.None, depth); var finalPos = font.TransformSingleCharacter(stringPos, charPosOffset, rotation, origin, scale, effects, stringSize, charSize);
font.DrawCharacter(batch, codePoint, character, finalPos, color, rotation, scale, effects, depth);
} }
/// <summary> /// <summary>

View file

@ -180,9 +180,13 @@ namespace MLEM.Formatting {
return null; return null;
} }
public void Draw(GameTime time, SpriteBatch batch, Vector2 pos, GenericFont font, Color color, float scale, float depth, float rotation = 0, Vector2 origin = default, SpriteEffects effects = SpriteEffects.None, int? startIndex = null, int? endIndex = null) {
this.Draw(time, batch, pos, font, color, new Vector2(scale), depth, rotation, origin, effects, startIndex, endIndex);
}
/// <inheritdoc cref="GenericFont.DrawString(SpriteBatch,string,Vector2,Color,float,Vector2,float,SpriteEffects,float)"/> /// <inheritdoc cref="GenericFont.DrawString(SpriteBatch,string,Vector2,Color,float,Vector2,float,SpriteEffects,float)"/>
public void Draw(GameTime time, SpriteBatch batch, Vector2 pos, GenericFont font, Color color, float scale, float depth, int? startIndex = null, int? endIndex = null) { public void Draw(GameTime time, SpriteBatch batch, Vector2 pos, GenericFont font, Color color, Vector2 scale, float depth, float rotation = 0, Vector2 origin = default, SpriteEffects effects = SpriteEffects.None, int? startIndex = null, int? endIndex = null) {
var innerOffset = new Vector2(this.initialInnerOffset * scale, 0); var innerOffset = new Vector2(this.initialInnerOffset, 0);
for (var t = 0; t < this.Tokens.Length; t++) { for (var t = 0; t < this.Tokens.Length; t++) {
var token = this.Tokens[t]; var token = this.Tokens[t];
if (endIndex != null && token.Index >= endIndex) if (endIndex != null && token.Index >= endIndex)
@ -192,8 +196,8 @@ namespace MLEM.Formatting {
var drawColor = token.GetColor(color); var drawColor = token.GetColor(color);
if (startIndex == null || token.Index >= startIndex) if (startIndex == null || token.Index >= startIndex)
token.DrawSelf(time, batch, pos + innerOffset, drawFont, drawColor, scale, depth); token.DrawSelf(time, batch, pos, innerOffset, drawFont, drawColor, scale, rotation, origin, depth, effects, this.area.Size);
innerOffset.X += token.GetSelfWidth(drawFont) * scale; innerOffset.X += token.GetSelfWidth(drawFont);
var indexInToken = 0; var indexInToken = 0;
for (var l = 0; l < token.SplitDisplayString.Length; l++) { for (var l = 0; l < token.SplitDisplayString.Length; l++) {
@ -205,19 +209,20 @@ namespace MLEM.Formatting {
var (codePoint, length) = line.GetCodePoint(cpsIndex); var (codePoint, length) = line.GetCodePoint(cpsIndex);
var character = CodePointSource.ToString(codePoint); var character = CodePointSource.ToString(codePoint);
var charSize = drawFont.MeasureString(character);
if (startIndex == null || token.Index + indexInToken >= startIndex) if (startIndex == null || token.Index + indexInToken >= startIndex)
token.DrawCharacter(time, batch, codePoint, character, indexInToken, pos + innerOffset, drawFont, drawColor, scale, depth); token.DrawCharacter(time, batch, codePoint, character, indexInToken, pos, innerOffset, drawFont, drawColor, scale, rotation, origin, depth, effects, this.area.Size, charSize);
innerOffset.X += drawFont.MeasureString(character).X * scale; innerOffset.X += charSize.X;
indexInToken += length; indexInToken += length;
cpsIndex += length; cpsIndex += length;
} }
// only split at a new line, not between tokens! // only split at a new line, not between tokens!
if (l < token.SplitDisplayString.Length - 1) { if (l < token.SplitDisplayString.Length - 1) {
innerOffset.X = token.InnerOffsets[l] * scale; innerOffset.X = token.InnerOffsets[l];
innerOffset.Y += drawFont.LineHeight * scale; innerOffset.Y += drawFont.LineHeight;
} }
} }
} }

View file

@ -257,43 +257,45 @@ public class GameImpl : MlemGame {
}).SetData("Ref", "Main"); }).SetData("Ref", "Main");
this.UiSystem.Add("SpillTest", spillPanel); this.UiSystem.Add("SpillTest", spillPanel);
var regularFont = spriteFont.Font; var regularFont = spriteFont.Font;
var genericFont = spriteFont; var genericFont = spriteFont;
var index = 0; var index = 0;
var pos = new Vector2(100, 20); var pos = new Vector2(100, 20);
var scale = 1F; var scale = 1F;
var origin = Vector2.Zero; var origin = Vector2.Zero;
var rotation = 0F; var rotation = 0F;
var effects = SpriteEffects.None; var effects = SpriteEffects.None;
this.OnDraw += (_, _) => { const string testString = "This is a\ntest string\n\twith long lines.\nLet's write some more stuff. Let's\r\nsplit lines weirdly.";
const string testString = "This is a\ntest string\n\twith long lines.\nLet's write some more stuff. Let's\r\nsplit lines weirdly."; var formatted = formatter.Tokenize(genericFont, testString);
if (MlemGame.Input.IsKeyPressed(Keys.I)) {
index++;
if (index == 1) {
scale = 2;
} else if (index == 2) {
origin = new Vector2(15, 15);
} else if (index == 3) {
rotation = 0.25F;
} else if (index == 4) {
effects = SpriteEffects.FlipHorizontally;
} else if (index == 5) {
effects = SpriteEffects.FlipVertically;
} else if (index == 6) {
effects = SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically;
}
}
this.SpriteBatch.Begin(); this.OnDraw += (_, time) => {
if (MlemGame.Input.IsKeyDown(Keys.LeftShift)) { if (MlemGame.Input.IsKeyPressed(Keys.I)) {
this.SpriteBatch.DrawString(regularFont, testString, pos, Color.Red, rotation, origin, scale, effects, 0); index++;
} else { if (index == 1) {
genericFont.DrawString(this.SpriteBatch, testString, pos, Color.Green, rotation, origin, scale, effects, 0); scale = 2;
} } else if (index == 2) {
this.SpriteBatch.End(); origin = new Vector2(15, 15);
}; } else if (index == 3) {
rotation = 0.25F;
} else if (index == 4) {
effects = SpriteEffects.FlipHorizontally;
} else if (index == 5) {
effects = SpriteEffects.FlipVertically;
} else if (index == 6) {
effects = SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically;
}
}
this.SpriteBatch.Begin();
if (MlemGame.Input.IsKeyDown(Keys.LeftShift)) {
this.SpriteBatch.DrawString(regularFont, testString, pos, Color.Red, rotation, origin, scale, effects, 0);
} else {
formatted.Draw(time, this.SpriteBatch, pos, genericFont, Color.Green, scale, 0, rotation, origin, effects);
}
this.SpriteBatch.End();
};
/*var viewport = new BoxingViewportAdapter(this.Window, this.GraphicsDevice, 1280, 720); /*var viewport = new BoxingViewportAdapter(this.Window, this.GraphicsDevice, 1280, 720);
var newPanel = new Panel(Anchor.TopLeft, new Vector2(200, 100), new Vector2(10, 10)); var newPanel = new Panel(Anchor.TopLeft, new Vector2(200, 100), new Vector2(10, 10));

View file

@ -2,7 +2,7 @@
#tool dotnet:?package=docfx&version=2.75.3 #tool dotnet:?package=docfx&version=2.75.3
// this is the upcoming version, for prereleases // this is the upcoming version, for prereleases
var version = Argument("version", "6.3.2"); var version = Argument("version", "7.0.0");
var target = Argument("target", "Default"); var target = Argument("target", "Default");
var gitRef = Argument("ref", "refs/heads/main"); var gitRef = Argument("ref", "refs/heads/main");
var buildNum = Argument("buildNum", ""); var buildNum = Argument("buildNum", "");