diff --git a/Demos/TextFormattingDemo.cs b/Demos/TextFormattingDemo.cs index 4c128bd..54112a0 100644 --- a/Demos/TextFormattingDemo.cs +++ b/Demos/TextFormattingDemo.cs @@ -75,6 +75,10 @@ namespace Demos { var size = this.tokenizedText.GetArea(Vector2.Zero, this.Scale).Size; var pos = new Vector2(this.GraphicsDevice.Viewport.Width / 2, (this.GraphicsDevice.Viewport.Height - size.Y) / 2); + var rotation = this.transform ? 0.25F : 0; + var origin = this.transform ? new Vector2(size.X / this.Scale, 0) : Vector2.Zero; + var effects = this.transform ? SpriteEffects.FlipHorizontally : SpriteEffects.None; + // draw bounds, which can be toggled with B in this demo if (this.drawBounds) { var blank = this.SpriteBatch.GetBlankTexture(); @@ -86,13 +90,14 @@ namespace Demos { } // 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.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.tokenizedText.Draw(time, this.SpriteBatch, pos, this.font, Color.White, this.Scale, 0, rotation, origin, effects, this.startIndex, this.endIndex); this.SpriteBatch.End(); + + // an example of how to interact with the text + var hovered = this.tokenizedText.GetTokenUnderPos(pos, this.InputHandler.ViewportMousePosition.ToVector2(), this.Scale, this.font, rotation, origin, effects); + if (hovered != null) + Console.WriteLine($"Hovering \"{hovered.Substring}\""); } public override void Update(GameTime time) { diff --git a/MLEM/Formatting/Token.cs b/MLEM/Formatting/Token.cs index 75830d4..34dd6c3 100644 --- a/MLEM/Formatting/Token.cs +++ b/MLEM/Formatting/Token.cs @@ -149,6 +149,11 @@ namespace MLEM.Formatting { font.DrawCharacter(batch, codePoint, character, finalPos, color, rotation, scale, effects, depth); } + /// + public IEnumerable GetArea(Vector2 stringPos, float scale) { + return this.GetArea(stringPos, new Vector2(scale)); + } + /// /// Gets a list of rectangles that encompass this token's area. /// This can be used to invoke events when the mouse is hovered over the token, for example. @@ -156,7 +161,7 @@ namespace MLEM.Formatting { /// The position that the string is drawn at /// The scale that the string is drawn at /// A set of rectangles that this token contains - public IEnumerable GetArea(Vector2 stringPos, float scale) { + public IEnumerable GetArea(Vector2 stringPos, Vector2 scale) { return this.Area.Select(a => new RectangleF(stringPos + a.Location * scale, a.Size * scale)); } diff --git a/MLEM/Formatting/TokenizedString.cs b/MLEM/Formatting/TokenizedString.cs index e600676..128795e 100644 --- a/MLEM/Formatting/TokenizedString.cs +++ b/MLEM/Formatting/TokenizedString.cs @@ -162,17 +162,30 @@ namespace MLEM.Formatting { code.Update(time); } + /// + public Token GetTokenUnderPos(Vector2 stringPos, Vector2 target, float scale, GenericFont font = null, float rotation = 0, Vector2 origin = default, SpriteEffects effects = SpriteEffects.None) { + return this.GetTokenUnderPos(stringPos, target, new Vector2(scale), font, rotation, origin, effects); + } + /// /// Returns the token under the given position. /// This can be used for hovering effects when the mouse is over a token, etc. /// - /// The position that the string is drawn at - /// The position to use for checking the token - /// The scale that the string is drawn at - /// The token under the target position - public Token GetTokenUnderPos(Vector2 stringPos, Vector2 target, float scale) { + /// The position that the string is drawn at. + /// The position to use for checking the token. + /// The scale that the string is drawn at. + /// The font that the string is being drawn with. If this is , all following parameters are ignored. + /// The rotation that the string is being drawn with. If is , this this is ignored. + /// The origin that the string is being drawn with. If is , this this is ignored. + /// The sprite effects that the string is being drawn with. If is , this is ignored. + /// The token under the target position^ + public Token GetTokenUnderPos(Vector2 stringPos, Vector2 target, Vector2 scale, GenericFont font = null, float rotation = 0, Vector2 origin = default, SpriteEffects effects = SpriteEffects.None) { + if (font != null) { + var transform = font.CalculateStringTransform(stringPos, rotation, origin, scale, effects, this.area.Size); + target = Vector2.Transform(target, Matrix.Invert(transform)); + } foreach (var token in this.Tokens) { - foreach (var rect in token.GetArea(stringPos, scale)) { + foreach (var rect in font != null ? token.GetArea(Vector2.Zero, 1) : token.GetArea(stringPos, scale)) { if (rect.Contains(target)) return token; }