From ec82da71084b391a540f75e3548458258abda9cc Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Tue, 4 Feb 2025 10:31:12 +0000 Subject: [PATCH] input-field: improve dynamic width (#647) * input-field: fixup dynamic width - Instead of not rendering placeholder text, if it does not fit into the input-field width, render it up until the input field size. - Improve updateWidth. * input-field: make sure dots center does not change during width anim --- src/renderer/widgets/PasswordInputField.cpp | 57 ++++++++++++--------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/renderer/widgets/PasswordInputField.cpp b/src/renderer/widgets/PasswordInputField.cpp index be602fd..4782a03 100644 --- a/src/renderer/widgets/PasswordInputField.cpp +++ b/src/renderer/widgets/PasswordInputField.cpp @@ -217,21 +217,21 @@ bool CPasswordInputField::draw(const SRenderData& data) { } } - const auto CURRDOTS = dots.currentAmount->value(); - const int DOTPAD = (inputFieldBox.h - passSize.y) / 2; - const int DOTAREAWIDTH = inputFieldBox.w - DOTPAD * 2; - const int MAXDOTS = std::round(DOTAREAWIDTH * 1.0 / (passSize.x + passSpacing)); - const int DOTFLOORED = std::floor(CURRDOTS); - const auto DOTALPHA = fontCol.a; + const auto CURRDOTS = dots.currentAmount->value(); + const double DOTPAD = (inputFieldBox.h - passSize.y) / 2.0; + const double DOTAREAWIDTH = inputFieldBox.w - DOTPAD * 2; + const int MAXDOTS = std::round(DOTAREAWIDTH * 1.0 / (passSize.x + passSpacing)); + const int DOTFLOORED = std::floor(CURRDOTS); + const auto DOTALPHA = fontCol.a; // Calculate the total width required for all dots including spaces between them - const int CURRWIDTH = (passSize.x + passSpacing) * CURRDOTS - passSpacing; + const double CURRWIDTH = (passSize.x + passSpacing) * CURRDOTS - passSpacing; // Calculate starting x-position to ensure dots stay centered within the input field - int xstart = dots.center ? (DOTAREAWIDTH - CURRWIDTH) / 2 + DOTPAD : DOTPAD; + double xstart = dots.center ? (DOTAREAWIDTH - CURRWIDTH) / 2.0 + DOTPAD : DOTPAD; if (CURRDOTS > MAXDOTS) - xstart = (inputFieldBox.w + MAXDOTS * (passSize.x + passSpacing) - passSpacing - 2 * CURRWIDTH) / 2; + xstart = (inputFieldBox.w + MAXDOTS * (passSize.x + passSpacing) - passSpacing - 2 * CURRWIDTH) / 2.0; if (dots.rounding == -1) dots.rounding = passSize.x / 2.0; @@ -249,9 +249,8 @@ bool CPasswordInputField::draw(const SRenderData& data) { fontCol.a *= (1 - CURRDOTS + DOTFLOORED) * data.opacity; } - Vector2D dotPosition = - inputFieldBox.pos() + Vector2D{xstart + (int)inputFieldBox.w % 2 / 2.0 + i * (passSize.x + passSpacing), inputFieldBox.h / 2.0 - passSize.y / 2.0}; - CBox box{dotPosition, passSize}; + Vector2D dotPosition = inputFieldBox.pos() + Vector2D{xstart + i * (passSize.x + passSpacing), inputFieldBox.h / 2.0 - passSize.y / 2.0}; + CBox box{dotPosition, passSize}; if (!dots.textFormat.empty()) { if (!dots.textAsset) { forceReload = true; @@ -260,9 +259,9 @@ bool CPasswordInputField::draw(const SRenderData& data) { } g_pRenderer->renderTexture(box, dots.textAsset->texture, fontCol.a, dots.rounding); - } else { + } else g_pRenderer->renderRect(box, fontCol, dots.rounding); - } + fontCol.a = DOTALPHA; } } @@ -275,11 +274,16 @@ bool CPasswordInputField::draw(const SRenderData& data) { currAsset = placeholder.asset; - if (currAsset && currAsset->texture.m_vSize.x + size->value().y <= size->value().x) { - Vector2D pos = outerBox.pos() + outerBox.size() / 2.f; - pos = pos - currAsset->texture.m_vSize / 2.f; - CBox textbox{pos, currAsset->texture.m_vSize}; - g_pRenderer->renderTexture(textbox, currAsset->texture, data.opacity * fade.a->value(), 0); + if (currAsset) { + const Vector2D ASSETPOS = inputFieldBox.pos() + inputFieldBox.size() / 2.0 - currAsset->texture.m_vSize / 2.0; + const CBox ASSETBOX{ASSETPOS, currAsset->texture.m_vSize}; + + // Cut the texture to the width of the input field + glEnable(GL_SCISSOR_TEST); + glScissor(inputFieldBox.x, inputFieldBox.y, inputFieldBox.w, inputFieldBox.h); + g_pRenderer->renderTexture(ASSETBOX, currAsset->texture, data.opacity * fade.a->value(), 0); + glScissor(0, 0, viewport.x, viewport.y); + glDisable(GL_SCISSOR_TEST); } else forceReload = true; } @@ -355,19 +359,24 @@ void CPasswordInputField::updatePlaceholder() { void CPasswordInputField::updateWidth() { double targetSizeX = configSize.x; - if (placeholder.asset) + if (passwordLength == 0 && placeholder.asset) targetSizeX = placeholder.asset->texture.m_vSize.x + size->goal().y; if (targetSizeX < configSize.x) targetSizeX = configSize.x; - if (size->goal().x != targetSizeX) + if (size->goal().x != targetSizeX) { *size = Vector2D{targetSizeX, configSize.y}; + size->setCallbackOnEnd([this](auto) { + redrawShadow = true; + pos = posFromHVAlign(viewport, size->value(), configPos, halign, valign); + }); + } - if (size->isBeingAnimated()) + if (size->isBeingAnimated()) { redrawShadow = true; - - pos = posFromHVAlign(viewport, size->value(), configPos, halign, valign); + pos = posFromHVAlign(viewport, size->value(), configPos, halign, valign); + } } void CPasswordInputField::updateHiddenInputState() {