From eb611d12dbe8bdb24fb976a79d5c3ea5f6cbc6e5 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Wed, 13 Oct 2021 18:18:23 +0200 Subject: [PATCH] Fixed some issues in FlexboxComponent. Also added some sanity checks and size restrictions to BadgeComponent and FlexboxComponent. --- es-core/src/components/BadgesComponent.cpp | 6 +- es-core/src/components/FlexboxComponent.cpp | 87 ++++++++++++++------- es-core/src/components/FlexboxComponent.h | 4 +- 3 files changed, 63 insertions(+), 34 deletions(-) diff --git a/es-core/src/components/BadgesComponent.cpp b/es-core/src/components/BadgesComponent.cpp index bce5eaeca..00c023b64 100644 --- a/es-core/src/components/BadgesComponent.cpp +++ b/es-core/src/components/BadgesComponent.cpp @@ -138,11 +138,11 @@ void BadgesComponent::applyTheme(const std::shared_ptr& theme, if (elem->has("itemMargin")) { const glm::vec2 itemMargin = elem->get("itemMargin"); - if (itemMargin.x < 0.0f || itemMargin.x > 100.0f || itemMargin.y < 0.0f || - itemMargin.y > 100.0f) { + if (itemMargin.x < 0.0f || itemMargin.x > 0.2f || itemMargin.y < 0.0f || + itemMargin.y > 0.2f) { LOG(LogWarning) << "BadgesComponent: Invalid theme configuration, set to \"" - << itemMargin.x << "x" << itemMargin.y << "\""; + << itemMargin.x << " " << itemMargin.y << "\""; } else { mFlexboxComponent.setItemMargin(itemMargin); diff --git a/es-core/src/components/FlexboxComponent.cpp b/es-core/src/components/FlexboxComponent.cpp index 4d921e47f..f9b81abd9 100644 --- a/es-core/src/components/FlexboxComponent.cpp +++ b/es-core/src/components/FlexboxComponent.cpp @@ -11,8 +11,8 @@ #define DEFAULT_ITEMS_PER_LINE 4 #define DEFAULT_LINES 2 #define DEFAULT_ITEM_PLACEMENT "center" -#define DEFAULT_MARGIN_X 10.0f -#define DEFAULT_MARGIN_Y 10.0f +#define DEFAULT_MARGIN_X std::roundf(0.01f * Renderer::getScreenWidth()) +#define DEFAULT_MARGIN_Y std::roundf(0.01f * Renderer::getScreenHeight()) #include "components/FlexboxComponent.h" @@ -33,6 +33,32 @@ FlexboxComponent::FlexboxComponent(Window* window, { } +void FlexboxComponent::render(const glm::mat4& parentTrans) +{ + if (!isVisible()) + return; + + if (!mLayoutValid) + computeLayout(); + + glm::mat4 trans{parentTrans * getTransform()}; + Renderer::setMatrix(trans); + + if (Settings::getInstance()->getBool("DebugImage")) + Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033); + + for (auto& image : mImages) { + if (mOpacity == 255) { + image.second.render(trans); + } + else { + image.second.setOpacity(mOpacity); + image.second.render(trans); + image.second.setOpacity(255); + } + } +} + void FlexboxComponent::computeLayout() { // Start placing items in the top-left. @@ -49,19 +75,35 @@ void FlexboxComponent::computeLayout() directionRow = {1, 0}; } + // If we're not clamping itemMargin to a reasonable value, all kinds of weird rendering + // issues could occur. + mItemMargin.x = glm::clamp(mItemMargin.x, 0.0f, mSize.x / 2.0f); + mItemMargin.y = glm::clamp(mItemMargin.y, 0.0f, mSize.y / 2.0f); + + // Also keep the size within reason. + mSize.x = glm::clamp(mSize.x, static_cast(Renderer::getScreenWidth()) * 0.03f, + static_cast(Renderer::getScreenWidth())); + mSize.y = glm::clamp(mSize.y, static_cast(Renderer::getScreenHeight()) * 0.03f, + static_cast(Renderer::getScreenHeight())); + // Compute maximum image dimensions. glm::vec2 grid; if (mDirection == "row") grid = {mItemsPerLine, mLines}; else grid = {mLines, mItemsPerLine}; + glm::vec2 maxItemSize{(mSize + mItemMargin - grid * mItemMargin) / grid}; + maxItemSize.x = floorf(maxItemSize.x); + maxItemSize.y = floorf(maxItemSize.y); if (grid.x * grid.y < static_cast(mImages.size())) { LOG(LogWarning) << "FlexboxComponent: Invalid theme configuration, the number of badges " "exceeds the product of times "; } + glm::vec2 sizeChange{0.0f, 0.0f}; + // Set final image dimensions. for (auto& image : mImages) { if (!image.second.isVisible()) @@ -78,9 +120,22 @@ void FlexboxComponent::computeLayout() newSize = sizeMaxX; else newSize = sizeMaxX.x * sizeMaxX.y >= sizeMaxY.x * sizeMaxY.y ? sizeMaxX : sizeMaxY; - image.second.setResize(newSize.x, newSize.y); + + if (image.second.getSize() != newSize) + image.second.setResize(newSize.x, newSize.y); + + // In case maxItemSize needs to be updated. + if (newSize.x != sizeChange.x) + sizeChange.x = newSize.x; + if (newSize.y != sizeChange.y) + sizeChange.y = newSize.y; } + if (maxItemSize.x != sizeChange.x) + maxItemSize.x = sizeChange.x; + if (maxItemSize.y != sizeChange.y) + maxItemSize.y = sizeChange.y; + // Pre-compute layout parameters. float anchorXStart{anchorX}; float anchorYStart{anchorY}; @@ -140,29 +195,3 @@ void FlexboxComponent::computeLayout() mLayoutValid = true; } - -void FlexboxComponent::render(const glm::mat4& parentTrans) -{ - if (!isVisible()) - return; - - if (!mLayoutValid) - computeLayout(); - - glm::mat4 trans{parentTrans * getTransform()}; - Renderer::setMatrix(trans); - - if (Settings::getInstance()->getBool("DebugImage")) - Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033); - - for (auto& image : mImages) { - if (mOpacity == 255) { - image.second.render(trans); - } - else { - image.second.setOpacity(mOpacity); - image.second.render(trans); - image.second.setOpacity(255); - } - } -} diff --git a/es-core/src/components/FlexboxComponent.h b/es-core/src/components/FlexboxComponent.h index bbe385aba..41c24433e 100644 --- a/es-core/src/components/FlexboxComponent.h +++ b/es-core/src/components/FlexboxComponent.h @@ -15,10 +15,10 @@ class FlexboxComponent : public GuiComponent { public: - explicit FlexboxComponent(Window* window, - std::vector>& images); + FlexboxComponent(Window* window, std::vector>& images); // Getters/setters for the layout. + std::string getDirection() const { return mDirection; } void setDirection(const std::string& direction) { assert(direction == "row" || direction == "column");