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
This commit is contained in:
Maximilian Seidler 2025-02-04 10:31:12 +00:00 committed by GitHub
parent 465148ac21
commit ec82da7108
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -217,21 +217,21 @@ bool CPasswordInputField::draw(const SRenderData& data) {
} }
} }
const auto CURRDOTS = dots.currentAmount->value(); const auto CURRDOTS = dots.currentAmount->value();
const int DOTPAD = (inputFieldBox.h - passSize.y) / 2; const double DOTPAD = (inputFieldBox.h - passSize.y) / 2.0;
const int DOTAREAWIDTH = inputFieldBox.w - DOTPAD * 2; const double DOTAREAWIDTH = inputFieldBox.w - DOTPAD * 2;
const int MAXDOTS = std::round(DOTAREAWIDTH * 1.0 / (passSize.x + passSpacing)); const int MAXDOTS = std::round(DOTAREAWIDTH * 1.0 / (passSize.x + passSpacing));
const int DOTFLOORED = std::floor(CURRDOTS); const int DOTFLOORED = std::floor(CURRDOTS);
const auto DOTALPHA = fontCol.a; const auto DOTALPHA = fontCol.a;
// Calculate the total width required for all dots including spaces between them // 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 // 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) 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) if (dots.rounding == -1)
dots.rounding = passSize.x / 2.0; dots.rounding = passSize.x / 2.0;
@ -249,9 +249,8 @@ bool CPasswordInputField::draw(const SRenderData& data) {
fontCol.a *= (1 - CURRDOTS + DOTFLOORED) * data.opacity; fontCol.a *= (1 - CURRDOTS + DOTFLOORED) * data.opacity;
} }
Vector2D dotPosition = Vector2D dotPosition = inputFieldBox.pos() + Vector2D{xstart + i * (passSize.x + passSpacing), inputFieldBox.h / 2.0 - passSize.y / 2.0};
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};
CBox box{dotPosition, passSize};
if (!dots.textFormat.empty()) { if (!dots.textFormat.empty()) {
if (!dots.textAsset) { if (!dots.textAsset) {
forceReload = true; forceReload = true;
@ -260,9 +259,9 @@ bool CPasswordInputField::draw(const SRenderData& data) {
} }
g_pRenderer->renderTexture(box, dots.textAsset->texture, fontCol.a, dots.rounding); g_pRenderer->renderTexture(box, dots.textAsset->texture, fontCol.a, dots.rounding);
} else { } else
g_pRenderer->renderRect(box, fontCol, dots.rounding); g_pRenderer->renderRect(box, fontCol, dots.rounding);
}
fontCol.a = DOTALPHA; fontCol.a = DOTALPHA;
} }
} }
@ -275,11 +274,16 @@ bool CPasswordInputField::draw(const SRenderData& data) {
currAsset = placeholder.asset; currAsset = placeholder.asset;
if (currAsset && currAsset->texture.m_vSize.x + size->value().y <= size->value().x) { if (currAsset) {
Vector2D pos = outerBox.pos() + outerBox.size() / 2.f; const Vector2D ASSETPOS = inputFieldBox.pos() + inputFieldBox.size() / 2.0 - currAsset->texture.m_vSize / 2.0;
pos = pos - currAsset->texture.m_vSize / 2.f; const CBox ASSETBOX{ASSETPOS, currAsset->texture.m_vSize};
CBox textbox{pos, currAsset->texture.m_vSize};
g_pRenderer->renderTexture(textbox, currAsset->texture, data.opacity * fade.a->value(), 0); // 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 } else
forceReload = true; forceReload = true;
} }
@ -355,19 +359,24 @@ void CPasswordInputField::updatePlaceholder() {
void CPasswordInputField::updateWidth() { void CPasswordInputField::updateWidth() {
double targetSizeX = configSize.x; double targetSizeX = configSize.x;
if (placeholder.asset) if (passwordLength == 0 && placeholder.asset)
targetSizeX = placeholder.asset->texture.m_vSize.x + size->goal().y; targetSizeX = placeholder.asset->texture.m_vSize.x + size->goal().y;
if (targetSizeX < configSize.x) if (targetSizeX < configSize.x)
targetSizeX = configSize.x; targetSizeX = configSize.x;
if (size->goal().x != targetSizeX) if (size->goal().x != targetSizeX) {
*size = Vector2D{targetSizeX, configSize.y}; *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; redrawShadow = true;
pos = posFromHVAlign(viewport, size->value(), configPos, halign, valign);
pos = posFromHVAlign(viewport, size->value(), configPos, halign, valign); }
} }
void CPasswordInputField::updateHiddenInputState() { void CPasswordInputField::updateHiddenInputState() {