From 3a9c7b92e3cd853bee63826a3b4f435022513764 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Thu, 1 Sep 2022 17:40:29 +0200 Subject: [PATCH] Added support for arbitrary image aspect ratios to RatingComponent. Also added an overlay property and fixed some potential crashes. --- es-core/src/ThemeData.cpp | 1 + es-core/src/components/RatingComponent.cpp | 66 +++++++++++++++------- es-core/src/components/RatingComponent.h | 2 + 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index 2b2ae4c0a..02072d05c 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -247,6 +247,7 @@ std::map> {"color", COLOR}, {"filledPath", PATH}, {"unfilledPath", PATH}, + {"overlay", BOOLEAN}, {"opacity", FLOAT}, {"visible", BOOLEAN}, {"zIndex", FLOAT}}}, diff --git a/es-core/src/components/RatingComponent.cpp b/es-core/src/components/RatingComponent.cpp index 4bc4ebcd1..5946c5230 100644 --- a/es-core/src/components/RatingComponent.cpp +++ b/es-core/src/components/RatingComponent.cpp @@ -15,11 +15,14 @@ RatingComponent::RatingComponent(bool colorizeChanges) : mRenderer {Renderer::getInstance()} + , mValue {0.5f} + , mImageRatio {1.0f} , mColorOriginalValue {DEFAULT_COLORSHIFT} , mColorChangedValue {DEFAULT_COLORSHIFT} , mColorShift {DEFAULT_COLORSHIFT} , mColorShiftEnd {DEFAULT_COLORSHIFT} , mColorizeChanges {colorizeChanges} + , mOverlay {true} { mSize = glm::vec2 {std::round(mRenderer->getScreenHeight() * 0.06f) * NUM_RATING_STARS, std::round(mRenderer->getScreenHeight() * 0.06f)}; @@ -32,8 +35,6 @@ RatingComponent::RatingComponent(bool colorizeChanges) mIconFilled.setImage(std::string(":/graphics/star_filled.svg"), true); mIconUnfilled.setImage(std::string(":/graphics/star_unfilled.svg"), true); - - mValue = 0.5f; } void RatingComponent::setValue(const std::string& value) @@ -70,8 +71,10 @@ void RatingComponent::setValue(const std::string& value) mValue = 0.0f; } - mIconFilled.setClipRegion( - glm::vec4 {0.0f, 0.0f, std::round(mIconFilled.getSize().x * mValue), mSize.y}); + const float clipValue {std::round(mIconUnfilled.getSize().x * mValue)}; + if (!mOverlay) + mIconUnfilled.setClipRegion(glm::vec4 {clipValue, 0.0f, mSize.x, mSize.y}); + mIconFilled.setClipRegion(glm::vec4 {0.0f, 0.0f, clipValue, mSize.y}); } std::string RatingComponent::getValue() const @@ -105,10 +108,12 @@ void RatingComponent::onSizeChanged() mSize.x = mSize.y * NUM_RATING_STARS; mIconFilled.getTexture()->setSize(mSize.y, mSize.y); - mIconFilled.setResize(glm::vec2 {mSize.y * NUM_RATING_STARS, mSize.y}, true); + mIconFilled.setResize(glm::vec2 {std::round(mSize.y * mImageRatio) * NUM_RATING_STARS, mSize.y}, + true); mIconUnfilled.getTexture()->setSize(mSize.y, mSize.y); - mIconUnfilled.setResize(glm::vec2 {mSize.y * NUM_RATING_STARS, mSize.y}, true); + mIconUnfilled.setResize( + glm::vec2 {std::round(mSize.y * mImageRatio) * NUM_RATING_STARS, mSize.y}, true); } void RatingComponent::render(const glm::mat4& parentTrans) @@ -141,8 +146,10 @@ bool RatingComponent::input(InputConfig* config, Input input) mIconFilled.setColorShift(mColorChangedValue); } - mIconFilled.setClipRegion( - glm::vec4 {0.0f, 0.0f, std::round(mIconFilled.getSize().x * mValue), mSize.y}); + const float clipValue {std::round(mIconUnfilled.getSize().x * mValue)}; + if (!mOverlay) + mIconUnfilled.setClipRegion(glm::vec4 {clipValue, 0.0f, mSize.x, mSize.y}); + mIconFilled.setClipRegion(glm::vec4 {0.0f, 0.0f, clipValue, mSize.y}); } return GuiComponent::input(config, input); @@ -165,6 +172,20 @@ void RatingComponent::applyTheme(const std::shared_ptr& theme, getParent()->getSize() : glm::vec2(Renderer::getScreenWidth(), Renderer::getScreenHeight())}; + { + // Read the image file in order to retrieve the image dimensions needed to calculate + // the aspect ratio constant. + if (properties & PATH && elem->has("filledPath")) { + std::string path {std::string(elem->get("filledPath"))}; + if (Utils::FileSystem::isRegularFile(path) || Utils::FileSystem::isSymlink(path)) { + auto tempImage = + TextureResource::get(path, false, false, false, false, 0, 0, 0.0f, 0.0f); + mImageRatio = static_cast(tempImage->getSize().x) / + static_cast(tempImage->getSize().y); + } + } + } + if (elem->has("size")) { glm::vec2 ratingSize {elem->get("size")}; if (ratingSize == glm::vec2 {0.0f, 0.0f}) { @@ -179,9 +200,9 @@ void RatingComponent::applyTheme(const std::shared_ptr& theme, ratingSize.y = glm::clamp(ratingSize.y, 0.01f, 0.5f); mSize = glm::round(ratingSize * scale); if (mSize.y == 0.0f) - mSize.y = mSize.x / NUM_RATING_STARS; + mSize.y = std::round(mSize.x / mImageRatio) / NUM_RATING_STARS; else - mSize.x = mSize.y * NUM_RATING_STARS; + mSize.x = std::round(mSize.y * mImageRatio) * NUM_RATING_STARS; } bool linearInterpolation {false}; @@ -204,36 +225,41 @@ void RatingComponent::applyTheme(const std::shared_ptr& theme, } } - mIconFilled.setTileSize(mSize.y, mSize.y); + mIconFilled.setTileSize(mSize.y * mImageRatio, mSize.y); mIconFilled.setResize(glm::vec2 {mSize}, false); - if (properties & PATH && elem->has("filledPath")) { + if (properties & PATH && elem->has("filledPath") && + (Utils::FileSystem::isRegularFile(elem->get("filledPath")) || + Utils::FileSystem::isSymlink(elem->get("filledPath")))) { mIconFilled.setDynamic(true); mIconFilled.setLinearInterpolation(linearInterpolation); mIconFilled.setImage(std::string(elem->get("filledPath")), true); - mIconFilled.getTexture()->setSize(mSize.y, mSize.y); - if (!mIconFilled.getTexture()->getScalable()) - mIconFilled.onSizeChanged(); + mIconFilled.getTexture()->setSize(std::round(mSize.y * mImageRatio), mSize.y); + mIconFilled.onSizeChanged(); } else { mIconFilled.setImage(std::string(":/graphics/star_filled.svg"), true); } - mIconUnfilled.setTileSize(mSize.y, mSize.y); + mIconUnfilled.setTileSize(mSize.y * mImageRatio, mSize.y); mIconUnfilled.setResize(glm::vec2 {mSize}, false); - if (properties & PATH && elem->has("unfilledPath")) { + if (properties & PATH && elem->has("unfilledPath") && + (Utils::FileSystem::isRegularFile(elem->get("unfilledPath")) || + Utils::FileSystem::isSymlink(elem->get("unfilledPath")))) { mIconUnfilled.setDynamic(true); mIconUnfilled.setLinearInterpolation(linearInterpolation); mIconUnfilled.setImage(std::string(elem->get("unfilledPath")), true); - mIconUnfilled.getTexture()->setSize(mSize.y, mSize.y); - if (!mIconUnfilled.getTexture()->getScalable()) - mIconUnfilled.onSizeChanged(); + mIconUnfilled.getTexture()->setSize(std::round(mSize.y * mImageRatio), mSize.y); + mIconUnfilled.onSizeChanged(); } else { mIconUnfilled.setImage(std::string(":/graphics/star_unfilled.svg"), true); } + if (elem->has("overlay") && !elem->get("overlay")) + mOverlay = false; + if (properties & COLOR) { if (elem->has("color")) { mIconFilled.setColorShift(elem->get("color")); diff --git a/es-core/src/components/RatingComponent.h b/es-core/src/components/RatingComponent.h index b7b5071f3..9a1659d4a 100644 --- a/es-core/src/components/RatingComponent.h +++ b/es-core/src/components/RatingComponent.h @@ -51,6 +51,7 @@ private: ImageComponent mIconUnfilled; float mValue; + float mImageRatio; int mOriginalValue; unsigned int mColorOriginalValue; @@ -59,6 +60,7 @@ private: unsigned int mColorShiftEnd; bool mColorizeChanges; + bool mOverlay; }; #endif // ES_APP_COMPONENTS_RATING_COMPONENT_H