From d58c5d8b3347957e9f5b0111de6390872b30a3f3 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 29 Jun 2022 14:34:13 +0200 Subject: [PATCH] fixed the new TextInput not updating correctly if the Font is set late --- MLEM/Input/TextInput.cs | 64 ++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/MLEM/Input/TextInput.cs b/MLEM/Input/TextInput.cs index c574247..228d51d 100644 --- a/MLEM/Input/TextInput.cs +++ b/MLEM/Input/TextInput.cs @@ -95,7 +95,7 @@ namespace MLEM.Input { if (this.caretPos != val) { this.caretPos = val; this.caretBlinkTimer = 0; - this.UpdateTextData(false); + this.SetTextDataDirty(false); } } } @@ -103,12 +103,22 @@ namespace MLEM.Input { /// The line of text that the caret is currently on. /// This can only be only non-0 if is true. /// - public int CaretLine { get; private set; } + public int CaretLine { + get { + this.UpdateTextDataIfDirty(); + return this.caretLine; + } + } /// /// The position in the current that the caret is currently on. /// If is false, this value is always equal to . /// - public int CaretPosInLine { get; private set; } + public int CaretPosInLine { + get { + this.UpdateTextDataIfDirty(); + return this.caretPosInLine; + } + } /// /// A character that should be displayed instead of this text input's content. /// The amount of masking characters displayed will be equal to the 's length. @@ -119,7 +129,7 @@ namespace MLEM.Input { set { if (this.maskingCharacter != value) { this.maskingCharacter = value; - this.UpdateTextData(false); + this.SetTextDataDirty(false); } } } @@ -138,7 +148,7 @@ namespace MLEM.Input { set { if (this.multiline != value) { this.multiline = value; - this.UpdateTextData(false); + this.SetTextDataDirty(false); } } } @@ -150,7 +160,7 @@ namespace MLEM.Input { set { if (this.font != value) { this.font = value; - this.UpdateTextData(false); + this.SetTextDataDirty(false); } } } @@ -163,7 +173,7 @@ namespace MLEM.Input { set { if (this.textScale != value) { this.textScale = value; - this.UpdateTextData(false); + this.SetTextDataDirty(false); } } } @@ -176,7 +186,7 @@ namespace MLEM.Input { set { if (this.size != value) { this.size = value; - this.UpdateTextData(false); + this.SetTextDataDirty(false); } } } @@ -200,11 +210,14 @@ namespace MLEM.Input { private int textOffset; private int lineOffset; private int caretPos; + private int caretLine; + private int caretPosInLine; private float caretDrawOffset; private bool multiline; private GenericFont font; private float textScale; private Vector2 size; + private bool textDataDirty; /// /// Creates a new text input with the given settings. @@ -259,6 +272,8 @@ namespace MLEM.Input { /// The current game time. /// The input handler to use for input querying. public void Update(GameTime time, InputHandler input) { + this.UpdateTextDataIfDirty(); + // FNA's text input event doesn't supply keys, so we handle this here #if FNA if (this.CaretPos > 0 && input.TryConsumePressed(Keys.Back)) { @@ -309,9 +324,7 @@ namespace MLEM.Input { /// The width that the caret should have, which is multiplied with before drawing. /// The color to draw the text and caret with. public void Draw(SpriteBatch batch, Vector2 textPos, float drawScale, float caretWidth, Color textColor) { - // handle first initialization if not done - if (this.displayedText == null) - this.UpdateTextData(false); + this.UpdateTextDataIfDirty(); var scale = this.TextScale * drawScale; this.Font.DrawString(batch, this.displayedText, textPos, textColor, 0, Vector2.Zero, scale, SpriteEffects.None, 0); @@ -339,7 +352,7 @@ namespace MLEM.Input { this.text.Clear(); this.text.Append(strg); this.CaretPos = this.text.Length; - this.UpdateTextData(); + this.SetTextDataDirty(); } /// @@ -356,7 +369,7 @@ namespace MLEM.Input { strg = strg.Substring(0, this.MaximumCharacters.Value - this.text.Length); this.text.Insert(this.CaretPos, strg); this.CaretPos += strg.Length; - this.UpdateTextData(); + this.SetTextDataDirty(); return true; } @@ -371,7 +384,7 @@ namespace MLEM.Input { this.text.Remove(index, length); // ensure that caret pos is still in bounds this.CaretPos = this.CaretPos; - this.UpdateTextData(); + this.SetTextDataDirty(); return true; } @@ -382,6 +395,7 @@ namespace MLEM.Input { /// The line to move the caret to /// True if the caret was moved, false if it was not (which indicates that the line with the given index does not exist) public bool MoveCaretToLine(int line) { + this.UpdateTextDataIfDirty(); var (destStart, destEnd) = this.GetLineBounds(line); if (destEnd > 0) { // find the position whose distance from the start is closest to the current distance from the start @@ -413,9 +427,16 @@ namespace MLEM.Input { return true; } - private void UpdateTextData(bool textChanged = true) { - if (this.Font == null) + private void SetTextDataDirty(bool textChanged = true) { + this.textDataDirty = true; + if (textChanged) + this.OnTextChange?.Invoke(this, this.Text); + } + + private void UpdateTextDataIfDirty() { + if (!this.textDataDirty || this.Font == null) return; + this.textDataDirty = false; if (this.Multiline) { // soft wrap if we're multiline this.splitText = this.Font.SplitStringSeparate(this.text, this.Size.X, this.TextScale).ToArray(); @@ -482,9 +503,6 @@ namespace MLEM.Input { if (this.MaskingCharacter != null) this.displayedText = new string(this.MaskingCharacter.Value, this.displayedText.Length); - - if (textChanged) - this.OnTextChange?.Invoke(this, this.Text); } private void UpdateCaretData() { @@ -496,8 +514,8 @@ namespace MLEM.Input { var split = this.splitText[d]; for (var i = 0; i <= split.Length; i++) { if (index == this.CaretPos) { - this.CaretLine = line; - this.CaretPosInLine = i - startOfLine; + this.caretLine = line; + this.caretPosInLine = i - startOfLine; this.caretDrawOffset = this.Font.MeasureString(split.Substring(startOfLine, this.CaretPosInLine)).X; return; } @@ -514,8 +532,8 @@ namespace MLEM.Input { line++; } } else if (this.displayedText != null) { - this.CaretLine = 0; - this.CaretPosInLine = this.CaretPos; + this.caretLine = 0; + this.caretPosInLine = this.CaretPos; this.caretDrawOffset = this.Font.MeasureString(this.displayedText.Substring(0, this.CaretPos - this.textOffset)).X; } }