From ac5b3b15e0760c17b5081f664918c07df81dbc19 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Tue, 20 Sep 2022 17:05:24 +0200 Subject: [PATCH] Added a new 'itemAxisHorizontal' property to the carousel. Also fixed a clipping issue when the vertical origin was not set to zero and cleaned up some code. --- es-core/src/ThemeData.cpp | 1 + .../components/primary/CarouselComponent.h | 144 +++++++++++------- 2 files changed, 93 insertions(+), 52 deletions(-) diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index 79d4b2261..fffc41aae 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -273,6 +273,7 @@ std::map> {"itemInterpolation", STRING}, {"itemRotation", FLOAT}, {"itemRotationOrigin", NORMALIZED_PAIR}, + {"itemAxisHorizontal", BOOLEAN}, {"itemHorizontalAlignment", STRING}, {"itemVerticalAlignment", STRING}, {"wheelHorizontalAlignment", STRING}, diff --git a/es-core/src/components/primary/CarouselComponent.h b/es-core/src/components/primary/CarouselComponent.h index 0b2452d10..92fdc7a8e 100644 --- a/es-core/src/components/primary/CarouselComponent.h +++ b/es-core/src/components/primary/CarouselComponent.h @@ -138,6 +138,7 @@ private: glm::vec2 mItemSize; bool mLinearInterpolation; bool mInstantItemTransitions; + bool mItemAxisHorizontal; float mItemScale; float mItemRotation; glm::vec2 mItemRotationOrigin; @@ -183,6 +184,7 @@ CarouselComponent::CarouselComponent() , mItemSize {Renderer::getScreenWidth() * 0.25f, Renderer::getScreenHeight() * 0.155f} , mLinearInterpolation {false} , mInstantItemTransitions {false} + , mItemAxisHorizontal {false} , mItemScale {1.2f} , mItemRotation {7.5f} , mItemRotationOrigin {-3.0f, 0.5f} @@ -519,14 +521,20 @@ template void CarouselComponent::render(const glm::mat4& parentT carouselTrans, glm::round(glm::vec3 {GuiComponent::mOrigin.x * mSize.x * -1.0f, GuiComponent::mOrigin.y * mSize.y * -1.0f, 0.0f})); - mRenderer->pushClipRect( - glm::ivec2 {static_cast(glm::clamp(std::round(carouselTrans[3].x), 0.0f, - mRenderer->getScreenWidth())), - static_cast(glm::clamp(std::round(carouselTrans[3].y), 0.0f, - mRenderer->getScreenHeight()))}, - glm::ivec2 {static_cast(std::min(std::round(mSize.x), mRenderer->getScreenWidth())), - static_cast(std::min(std::round(mSize.y), mRenderer->getScreenHeight()))}); + if (carouselTrans[3].x + mSize.x <= 0.0f || carouselTrans[3].y + mSize.y <= 0.0f) + return; + const float sizeY {carouselTrans[3].y < 0.0f ? mSize.y + carouselTrans[3].y : mSize.y}; + + glm::ivec2 clipPos {static_cast(glm::clamp(std::round(carouselTrans[3].x), 0.0f, + mRenderer->getScreenWidth())), + static_cast(glm::clamp(std::round(carouselTrans[3].y), 0.0f, + mRenderer->getScreenHeight()))}; + glm::ivec2 clipDim { + static_cast(std::min(std::round(mSize.x), mRenderer->getScreenWidth())), + static_cast(std::min(std::round(sizeY), mRenderer->getScreenHeight()))}; + + mRenderer->pushClipRect(clipPos, clipDim); mRenderer->setMatrix(carouselTrans); // In image debug mode, draw a green rectangle covering the entire carousel area. @@ -735,8 +743,36 @@ template void CarouselComponent::render(const glm::mat4& parentT continue; if (mType == CarouselType::VERTICAL_WHEEL || mType == CarouselType::HORIZONTAL_WHEEL) { - comp->setRotationDegrees(mItemRotation * renderItem.distance); - comp->setRotationOrigin(mItemRotationOrigin); + if (mItemAxisHorizontal) { + glm::mat4 positionCalc {renderItem.trans}; + const glm::vec2 rotationSize {comp->getSize()}; + const float xOff {(GuiComponent::mOrigin.x - mItemRotationOrigin.x) * + rotationSize.x}; + const float yOff {(GuiComponent::mOrigin.y - mItemRotationOrigin.y) * + rotationSize.y}; + + // Transform to offset point. + if (xOff != 0.0f || yOff != 0.0f) + positionCalc = + glm::translate(positionCalc, glm::vec3 {xOff * -1.0f, yOff * -1.0f, 0.0f}); + + // Apply rotation transform. + positionCalc = + glm::rotate(positionCalc, glm::radians(mItemRotation * renderItem.distance), + glm::vec3 {0.0f, 0.0f, 1.0f}); + + // Transform back to original point. + if (xOff != 0.0f || yOff != 0.0f) + positionCalc = glm::translate(positionCalc, glm::vec3 {xOff, yOff, 0.0f}); + + // Only keep position and discard the rotation data. + renderItem.trans[3].x = positionCalc[3].x; + renderItem.trans[3].y = positionCalc[3].y; + } + else { + comp->setRotationDegrees(mItemRotation * renderItem.distance); + comp->setRotationOrigin(mItemRotationOrigin); + } } comp->setScale(renderItem.scale); @@ -845,49 +881,6 @@ void CarouselComponent::applyTheme(const std::shared_ptr& theme, if (!mLegacyMode) { mLinearInterpolation = true; - if (elem->has("itemScale")) - mItemScale = glm::clamp(elem->get("itemScale"), 0.5f, 3.0f); - - if (elem->has("itemInterpolation")) { - const std::string itemInterpolation {elem->get("itemInterpolation")}; - if (itemInterpolation == "linear") { - mLinearInterpolation = true; - } - else if (itemInterpolation == "nearest") { - mLinearInterpolation = false; - } - else { - mLinearInterpolation = true; - LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " - "\"itemInterpolation\" for element \"" - << element.substr(9) << "\" defined as \"" << itemInterpolation - << "\""; - } - } - - if (elem->has("itemTransitions")) { - const std::string itemTransitions {elem->get("itemTransitions")}; - if (itemTransitions == "slide") { - mInstantItemTransitions = false; - } - else if (itemTransitions == "instant") { - mInstantItemTransitions = true; - } - else { - mInstantItemTransitions = false; - LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " - "\"itemTransitions\" for element \"" - << element.substr(9) << "\" defined as \"" << itemTransitions - << "\""; - } - } - - if (elem->has("itemSize")) { - const glm::vec2 itemSize {glm::clamp(elem->get("itemSize"), 0.05f, 1.0f)}; - mItemSize = - itemSize * glm::vec2(Renderer::getScreenWidth(), Renderer::getScreenHeight()); - } - if (elem->has("maxItemCount")) { mMaxItemCount = glm::clamp(elem->get("maxItemCount"), 0.5f, 30.0f); if (mType == CarouselType::HORIZONTAL_WHEEL || mType == CarouselType::VERTICAL_WHEEL) { @@ -909,11 +902,58 @@ void CarouselComponent::applyTheme(const std::shared_ptr& theme, mItemsAfterCenter = glm::clamp(static_cast(elem->get("itemsAfterCenter")), 0, 20); + if (elem->has("itemSize")) { + const glm::vec2 itemSize {glm::clamp(elem->get("itemSize"), 0.05f, 1.0f)}; + mItemSize = + itemSize * glm::vec2(Renderer::getScreenWidth(), Renderer::getScreenHeight()); + } + + if (elem->has("itemScale")) + mItemScale = glm::clamp(elem->get("itemScale"), 0.5f, 3.0f); + + if (elem->has("itemTransitions")) { + const std::string itemTransitions {elem->get("itemTransitions")}; + if (itemTransitions == "slide") { + mInstantItemTransitions = false; + } + else if (itemTransitions == "instant") { + mInstantItemTransitions = true; + } + else { + mInstantItemTransitions = false; + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + "\"itemTransitions\" for element \"" + << element.substr(9) << "\" defined as \"" << itemTransitions + << "\""; + } + } + + if (elem->has("itemInterpolation")) { + const std::string itemInterpolation {elem->get("itemInterpolation")}; + if (itemInterpolation == "linear") { + mLinearInterpolation = true; + } + else if (itemInterpolation == "nearest") { + mLinearInterpolation = false; + } + else { + mLinearInterpolation = true; + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + "\"itemInterpolation\" for element \"" + << element.substr(9) << "\" defined as \"" << itemInterpolation + << "\""; + } + } + if (elem->has("itemRotation")) mItemRotation = elem->get("itemRotation"); + if (elem->has("itemRotationOrigin")) mItemRotationOrigin = elem->get("itemRotationOrigin"); + mItemAxisHorizontal = + (elem->has("itemAxisHorizontal") && elem->get("itemAxisHorizontal")); + if (elem->has("itemHorizontalAlignment")) { const std::string alignment {elem->get("itemHorizontalAlignment")}; if (alignment == "left" && mType != CarouselType::HORIZONTAL) {