diff --git a/CHANGELOG.md b/CHANGELOG.md index 35c3d85..c0a785a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Improvements - Increased TextFormatter macro recursion limit to 64 - Allow changing the default values used by default TextFormatter codes - Allow setting ExternalGestureHandling through the InputHandler constructor +- Allow specifying start and end indices when drawing a TokenizedString Fixes - Fixed control characters being included in TextInput @@ -40,6 +41,7 @@ Additions Improvements - Increased Element area calculation recursion limit to 64 - Improved the SquishingGroup algorithm by prioritizing each element's final size +- Allow specifying start and end indices when drawing a Paragraph Fixes - Fixed images not updating their hidden state properly when the displayed texture changes diff --git a/Demos/TextFormattingDemo.cs b/Demos/TextFormattingDemo.cs index 2170d56..95d1354 100644 --- a/Demos/TextFormattingDemo.cs +++ b/Demos/TextFormattingDemo.cs @@ -34,6 +34,8 @@ namespace Demos { return TextFormattingDemo.DefaultScale * Math.Min(viewport.Width / 1280F, viewport.Height / 720F); } } + private int startIndex; + private int endIndex; public TextFormattingDemo(MlemGame game) : base(game) {} @@ -60,6 +62,7 @@ namespace Demos { // we specify our text alignment here too, so that all data is cached correctly for display this.tokenizedText = this.formatter.Tokenize(this.font, TextFormattingDemo.Text, TextAlignment.Center); this.tokenizedText.Split(this.font, this.GraphicsDevice.Viewport.Width * TextFormattingDemo.WidthMultiplier, this.Scale, TextAlignment.Center); + this.endIndex = this.tokenizedText.String.Length; } public override void DoDraw(GameTime time) { @@ -81,8 +84,8 @@ namespace Demos { } } - // draw the text itself - this.tokenizedText.Draw(time, this.SpriteBatch, pos, this.font, Color.White, this.Scale, 0); + // 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.SpriteBatch.End(); } @@ -90,8 +93,18 @@ namespace Demos { public override void Update(GameTime time) { // update our tokenized string to animate the animation codes this.tokenizedText.Update(time); + + // change some demo showcase info based on keybinds if (this.InputHandler.IsPressed(Keys.B)) this.drawBounds = !this.drawBounds; + if (this.startIndex > 0 && this.InputHandler.IsDown(Keys.Left)) + this.startIndex--; + if (this.startIndex < this.tokenizedText.String.Length && this.InputHandler.IsDown(Keys.Right)) + this.startIndex++; + if (this.endIndex > 0 && this.InputHandler.IsDown(Keys.Down)) + this.endIndex--; + if (this.endIndex < this.tokenizedText.String.Length && this.InputHandler.IsDown(Keys.Up)) + this.endIndex++; } public override void Clear() { diff --git a/MLEM.Ui/Elements/Paragraph.cs b/MLEM.Ui/Elements/Paragraph.cs index 1bd9eb1..a6950f8 100644 --- a/MLEM.Ui/Elements/Paragraph.cs +++ b/MLEM.Ui/Elements/Paragraph.cs @@ -139,6 +139,16 @@ namespace MLEM.Ui.Elements { this.SetTextDirty(); } } + /// + /// The inclusive index in this paragraph's to start drawing at. + /// This value is passed to . + /// + public int? DrawStartIndex; + /// + /// The exclusive index in this paragraph's to stop drawing at. + /// This value is passed to . + /// + public int? DrawEndIndex; /// public override bool IsHidden => base.IsHidden || string.IsNullOrWhiteSpace(this.Text); @@ -206,7 +216,7 @@ namespace MLEM.Ui.Elements { var pos = this.DisplayArea.Location + new Vector2(this.GetAlignmentOffset(), 0); var sc = this.TextScale * this.TextScaleMultiplier * this.Scale; var color = this.TextColor.OrDefault(Color.White) * alpha; - this.TokenizedText.Draw(time, batch, pos, this.RegularFont, color, sc, 0); + this.TokenizedText.Draw(time, batch, pos, this.RegularFont, color, sc, 0, this.DrawStartIndex, this.DrawEndIndex); base.Draw(time, batch, alpha, context); } diff --git a/MLEM/Formatting/TokenizedString.cs b/MLEM/Formatting/TokenizedString.cs index 54a30b7..db49998 100644 --- a/MLEM/Formatting/TokenizedString.cs +++ b/MLEM/Formatting/TokenizedString.cs @@ -189,29 +189,37 @@ namespace MLEM.Formatting { } /// - 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, int? startIndex = null, int? endIndex = null) { var innerOffset = new Vector2(this.initialInnerOffset * scale, 0); for (var t = 0; t < this.Tokens.Length; t++) { var token = this.Tokens[t]; + if (endIndex != null && token.Index >= endIndex) + return; + var drawFont = token.GetFont(font); var drawColor = token.GetColor(color); - token.DrawSelf(time, batch, pos + innerOffset, drawFont, drawColor, scale, depth); + if (startIndex == null || token.Index >= startIndex) + token.DrawSelf(time, batch, pos + innerOffset, drawFont, drawColor, scale, depth); innerOffset.X += token.GetSelfWidth(drawFont) * scale; var indexInToken = 0; for (var l = 0; l < token.SplitDisplayString.Length; l++) { - var charIndex = 0; + var cpsIndex = 0; var line = new CodePointSource(token.SplitDisplayString[l]); - while (charIndex < line.Length) { - var (codePoint, length) = line.GetCodePoint(charIndex); + while (cpsIndex < line.Length) { + if (endIndex != null && token.Index + indexInToken >= endIndex) + return; + + var (codePoint, length) = line.GetCodePoint(cpsIndex); var character = CodePointSource.ToString(codePoint); - token.DrawCharacter(time, batch, codePoint, character, indexInToken, pos + innerOffset, drawFont, drawColor, scale, depth); + if (startIndex == null || token.Index + indexInToken >= startIndex) + token.DrawCharacter(time, batch, codePoint, character, indexInToken, pos + innerOffset, drawFont, drawColor, scale, depth); innerOffset.X += drawFont.MeasureString(character).X * scale; - charIndex += length; - indexInToken++; + indexInToken += length; + cpsIndex += length; } // only split at a new line, not between tokens!