mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
Added a scaleInwards property to the grid element to contain scaling within the element boundaries
This commit is contained in:
parent
6cfa888b4d
commit
88df22cb61
|
@ -209,6 +209,7 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
|
||||||
{"itemSize", NORMALIZED_PAIR},
|
{"itemSize", NORMALIZED_PAIR},
|
||||||
{"itemScale", FLOAT},
|
{"itemScale", FLOAT},
|
||||||
{"itemSpacing", NORMALIZED_PAIR},
|
{"itemSpacing", NORMALIZED_PAIR},
|
||||||
|
{"scaleInwards", BOOLEAN},
|
||||||
{"fractionalRows", BOOLEAN},
|
{"fractionalRows", BOOLEAN},
|
||||||
{"itemTransitions", STRING},
|
{"itemTransitions", STRING},
|
||||||
{"rowTransitions", STRING},
|
{"rowTransitions", STRING},
|
||||||
|
|
|
@ -151,6 +151,7 @@ private:
|
||||||
glm::vec2 mItemSize;
|
glm::vec2 mItemSize;
|
||||||
float mItemScale;
|
float mItemScale;
|
||||||
glm::vec2 mItemSpacing;
|
glm::vec2 mItemSpacing;
|
||||||
|
bool mScaleInwards;
|
||||||
bool mFractionalRows;
|
bool mFractionalRows;
|
||||||
bool mInstantItemTransitions;
|
bool mInstantItemTransitions;
|
||||||
bool mInstantRowTransitions;
|
bool mInstantRowTransitions;
|
||||||
|
@ -222,6 +223,7 @@ GridComponent<T>::GridComponent()
|
||||||
mRenderer->getScreenHeight() * 0.25f}}
|
mRenderer->getScreenHeight() * 0.25f}}
|
||||||
, mItemScale {1.05f}
|
, mItemScale {1.05f}
|
||||||
, mItemSpacing {0.0f, 0.0f}
|
, mItemSpacing {0.0f, 0.0f}
|
||||||
|
, mScaleInwards {false}
|
||||||
, mFractionalRows {false}
|
, mFractionalRows {false}
|
||||||
, mInstantItemTransitions {false}
|
, mInstantItemTransitions {false}
|
||||||
, mInstantRowTransitions {false}
|
, mInstantRowTransitions {false}
|
||||||
|
@ -500,8 +502,10 @@ template <typename T> void GridComponent<T>::calculateLayout()
|
||||||
mVerticalMargin = 0.0f;
|
mVerticalMargin = 0.0f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mHorizontalMargin = ((mItemSize.x * mItemScale) - mItemSize.x) / 2.0f;
|
mHorizontalMargin =
|
||||||
mVerticalMargin = ((mItemSize.y * mItemScale) - mItemSize.y) / 2.0f;
|
((mItemSize.x * (mScaleInwards ? 1.0f : mItemScale)) - mItemSize.x) / 2.0f;
|
||||||
|
mVerticalMargin =
|
||||||
|
((mItemSize.y * (mScaleInwards ? 1.0f : mItemScale)) - mItemSize.y) / 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
int columnCount {0};
|
int columnCount {0};
|
||||||
|
@ -702,43 +706,54 @@ template <typename T> void GridComponent<T>::render(const glm::mat4& parentTrans
|
||||||
|
|
||||||
trans[3].y -= (mItemSize.y + mItemSpacing.y) * mScrollPos;
|
trans[3].y -= (mItemSize.y + mItemSpacing.y) * mScrollPos;
|
||||||
|
|
||||||
auto selectorRenderFunc = [this, &trans](std::vector<size_t>::const_iterator it,
|
auto calculateOffsetPos = [this](const glm::vec3& itemPos, const glm::vec2& origin,
|
||||||
const float scale, const float opacity,
|
const float scale,
|
||||||
const bool cursorEntry, const bool lastCursorEntry) {
|
const float relativeScale) -> const glm::vec2 {
|
||||||
|
const float sizeX {mItemSize.x * scale * relativeScale};
|
||||||
|
const float sizeY {mItemSize.y * scale * relativeScale};
|
||||||
|
glm::vec2 position {0.0f, 0.0f};
|
||||||
|
|
||||||
|
position.x = itemPos.x - (mItemSize.x / 2.0f);
|
||||||
|
position.x -= ((mItemSize.x * scale) - mItemSize.x) * origin.x;
|
||||||
|
position.x += ((mItemSize.x * scale) - sizeX) / 2.0f;
|
||||||
|
|
||||||
|
position.y = itemPos.y - (mItemSize.y / 2.0f);
|
||||||
|
position.y -= ((mItemSize.y * scale) - mItemSize.y) * origin.y;
|
||||||
|
position.y += ((mItemSize.y * scale) - sizeY) / 2.0f;
|
||||||
|
|
||||||
|
return position;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto selectorRenderFunc = [this, &trans, calculateOffsetPos](
|
||||||
|
std::vector<size_t>::const_iterator it, const glm::vec3& itemPos,
|
||||||
|
const float scale, glm::vec2 origin, glm::vec2 offset,
|
||||||
|
const float opacity) {
|
||||||
|
if (mSelectorImage == nullptr && !mHasSelectorColor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const glm::vec2 position {
|
||||||
|
calculateOffsetPos(itemPos, origin, scale, mSelectorRelativeScale)};
|
||||||
|
|
||||||
if (mSelectorImage != nullptr) {
|
if (mSelectorImage != nullptr) {
|
||||||
mSelectorImage->setPosition(mEntries.at(*it).data.item->getPosition());
|
mSelectorImage->setOrigin(0.0f, 0.0f);
|
||||||
|
mSelectorImage->setPosition(position.x, position.y);
|
||||||
mSelectorImage->setScale(scale);
|
mSelectorImage->setScale(scale);
|
||||||
mSelectorImage->setOpacity(opacity);
|
mSelectorImage->setOpacity(opacity);
|
||||||
mSelectorImage->render(trans);
|
mSelectorImage->render(trans);
|
||||||
}
|
}
|
||||||
else if (mHasSelectorColor) {
|
else if (mHasSelectorColor) {
|
||||||
// If a selector color is set but no selector image, then render a rectangle.
|
// If a selector color is set but no selector image, then render a rectangle.
|
||||||
const float sizeX {mItemSize.x * (cursorEntry || lastCursorEntry ? scale : 1.0f) *
|
const float sizeX {mItemSize.x * scale * mSelectorRelativeScale};
|
||||||
mSelectorRelativeScale};
|
const float sizeY {mItemSize.y * scale * mSelectorRelativeScale};
|
||||||
const float sizeY {mItemSize.y * (cursorEntry || lastCursorEntry ? scale : 1.0f) *
|
|
||||||
mSelectorRelativeScale};
|
|
||||||
float posX {mEntries.at(*it).data.item->getPosition().x - mItemSize.x * 0.5f};
|
|
||||||
float posY {mEntries.at(*it).data.item->getPosition().y - mItemSize.y * 0.5f};
|
|
||||||
|
|
||||||
if (cursorEntry || lastCursorEntry) {
|
|
||||||
posX -= ((mItemSize.x * scale * mSelectorRelativeScale) - mItemSize.x) / 2.0f;
|
|
||||||
posY -= ((mItemSize.y * scale * mSelectorRelativeScale) - mItemSize.y) / 2.0f;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
posX -= ((mItemSize.x * mSelectorRelativeScale) - mItemSize.x) / 2.0f;
|
|
||||||
posY -= ((mItemSize.y * mSelectorRelativeScale) - mItemSize.y) / 2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
mRenderer->setMatrix(trans);
|
mRenderer->setMatrix(trans);
|
||||||
mRenderer->drawRect(posX, posY, sizeX, sizeY, mSelectorColor, mSelectorColorEnd,
|
mRenderer->drawRect(position.x, position.y, sizeX, sizeY, mSelectorColor,
|
||||||
mSelectorColorGradientHorizontal, opacity);
|
mSelectorColorEnd, mSelectorColorGradientHorizontal, opacity);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto it = renderEntries.cbegin(); it != renderEntries.cend(); ++it) {
|
for (auto it = renderEntries.cbegin(); it != renderEntries.cend(); ++it) {
|
||||||
float metadataOpacity {1.0f};
|
float metadataOpacity {1.0f};
|
||||||
bool cursorEntry {false};
|
bool cursorEntry {false};
|
||||||
bool lastCursorEntry {false};
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, FileData*>) {
|
if constexpr (std::is_same_v<T, FileData*>) {
|
||||||
// If a game is marked as hidden, lower the opacity a lot.
|
// If a game is marked as hidden, lower the opacity a lot.
|
||||||
|
@ -765,7 +780,6 @@ template <typename T> void GridComponent<T>::render(const glm::mat4& parentTrans
|
||||||
dimming = glm::mix(mUnfocusedItemDimming, 1.0f, mTransitionFactor);
|
dimming = glm::mix(mUnfocusedItemDimming, 1.0f, mTransitionFactor);
|
||||||
}
|
}
|
||||||
else if (*it == static_cast<size_t>(mLastCursor)) {
|
else if (*it == static_cast<size_t>(mLastCursor)) {
|
||||||
lastCursorEntry = true;
|
|
||||||
scale = glm::mix(mItemScale, 1.0f, mTransitionFactor);
|
scale = glm::mix(mItemScale, 1.0f, mTransitionFactor);
|
||||||
opacity = glm::mix(1.0f * metadataOpacity, mUnfocusedItemOpacity * metadataOpacity,
|
opacity = glm::mix(1.0f * metadataOpacity, mUnfocusedItemOpacity * metadataOpacity,
|
||||||
mTransitionFactor);
|
mTransitionFactor);
|
||||||
|
@ -775,11 +789,56 @@ template <typename T> void GridComponent<T>::render(const glm::mat4& parentTrans
|
||||||
dimming = glm::mix(1.0f, mUnfocusedItemDimming, mTransitionFactor);
|
dimming = glm::mix(1.0f, mUnfocusedItemDimming, mTransitionFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const glm::vec3 itemPos {mEntries.at(*it).data.item->getPosition()};
|
||||||
|
glm::vec2 originInwards {0.5f, 0.5f};
|
||||||
|
glm::vec2 offsetInwards {0.0f, 0.0f};
|
||||||
|
|
||||||
|
if (mScaleInwards && scale != 1.0f) {
|
||||||
|
if (static_cast<int>(*it) < mColumns) {
|
||||||
|
// First row.
|
||||||
|
originInwards.y = 0.0f;
|
||||||
|
offsetInwards.y = mItemSize.y / 2.0f;
|
||||||
|
}
|
||||||
|
if ((itemPos.y + (mItemSize.y / 2.0f) * mItemScale) > mSize.y) {
|
||||||
|
// Scaled image won't fit vertically at the bottom.
|
||||||
|
originInwards.y = 1.0f;
|
||||||
|
offsetInwards.y = -(mItemSize.y / 2.0f);
|
||||||
|
}
|
||||||
|
if (static_cast<int>(*it) % mColumns == 0) {
|
||||||
|
// Leftmost column.
|
||||||
|
originInwards.x = 0.0f;
|
||||||
|
offsetInwards.x = mItemSize.x / 2.0f;
|
||||||
|
}
|
||||||
|
if (static_cast<int>(*it) % mColumns == mColumns - 1) {
|
||||||
|
// Rightmost column.
|
||||||
|
originInwards.x = 1.0f;
|
||||||
|
offsetInwards.x = -(mItemSize.x / 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec2 position {
|
||||||
|
calculateOffsetPos(itemPos, originInwards, scale,
|
||||||
|
(mEntries.at(*it).data.imagePath.empty() &&
|
||||||
|
mEntries.at(*it).data.defaultImagePath.empty() ?
|
||||||
|
mTextRelativeScale :
|
||||||
|
mImageRelativeScale))};
|
||||||
|
mEntries.at(*it).data.item->setOrigin(0.0f, 0.0f);
|
||||||
|
mEntries.at(*it).data.item->setPosition(position.x, position.y);
|
||||||
|
}
|
||||||
|
|
||||||
if (cursorEntry && mSelectorLayer == SelectorLayer::BOTTOM)
|
if (cursorEntry && mSelectorLayer == SelectorLayer::BOTTOM)
|
||||||
selectorRenderFunc(it, scale, opacity, cursorEntry, lastCursorEntry);
|
selectorRenderFunc(it, itemPos, scale, originInwards, offsetInwards, opacity);
|
||||||
|
|
||||||
|
glm::vec2 backgroundPos {
|
||||||
|
calculateOffsetPos(itemPos, originInwards, scale, mBackgroundRelativeScale)};
|
||||||
|
|
||||||
if (mBackgroundImage != nullptr) {
|
if (mBackgroundImage != nullptr) {
|
||||||
mBackgroundImage->setPosition(mEntries.at(*it).data.item->getPosition());
|
if (mScaleInwards && scale != 1.0f) {
|
||||||
|
mBackgroundImage->setOrigin(0.0f, 0.0f);
|
||||||
|
mBackgroundImage->setPosition(backgroundPos.x, backgroundPos.y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mBackgroundImage->setPosition(mEntries.at(*it).data.item->getPosition());
|
||||||
|
}
|
||||||
mBackgroundImage->setScale(scale);
|
mBackgroundImage->setScale(scale);
|
||||||
mBackgroundImage->setOpacity(opacity);
|
mBackgroundImage->setOpacity(opacity);
|
||||||
if (mHasUnfocusedItemSaturation)
|
if (mHasUnfocusedItemSaturation)
|
||||||
|
@ -787,32 +846,20 @@ template <typename T> void GridComponent<T>::render(const glm::mat4& parentTrans
|
||||||
if (mUnfocusedItemDimming != 1.0f)
|
if (mUnfocusedItemDimming != 1.0f)
|
||||||
mBackgroundImage->setDimming(dimming);
|
mBackgroundImage->setDimming(dimming);
|
||||||
mBackgroundImage->render(trans);
|
mBackgroundImage->render(trans);
|
||||||
|
if (mScaleInwards && scale != 1.0f)
|
||||||
|
mBackgroundImage->setOrigin(0.5f, 0.5f);
|
||||||
}
|
}
|
||||||
else if (mHasBackgroundColor) {
|
else if (mHasBackgroundColor) {
|
||||||
// If a background color is set but no background image, then render a rectangle.
|
// If a background color is set but no background image, then render a rectangle.
|
||||||
const float sizeX {mItemSize.x * (cursorEntry || lastCursorEntry ? scale : 1.0f) *
|
const float sizeX {mItemSize.x * scale * mBackgroundRelativeScale};
|
||||||
mBackgroundRelativeScale};
|
const float sizeY {mItemSize.y * scale * mBackgroundRelativeScale};
|
||||||
const float sizeY {mItemSize.y * (cursorEntry || lastCursorEntry ? scale : 1.0f) *
|
|
||||||
mBackgroundRelativeScale};
|
|
||||||
float posX {mEntries.at(*it).data.item->getPosition().x - mItemSize.x * 0.5f};
|
|
||||||
float posY {mEntries.at(*it).data.item->getPosition().y - mItemSize.y * 0.5f};
|
|
||||||
|
|
||||||
if (cursorEntry || lastCursorEntry) {
|
|
||||||
posX -= ((mItemSize.x * scale * mBackgroundRelativeScale) - mItemSize.x) / 2.0f;
|
|
||||||
posY -= ((mItemSize.y * scale * mBackgroundRelativeScale) - mItemSize.y) / 2.0f;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
posX -= ((mItemSize.x * mBackgroundRelativeScale) - mItemSize.x) / 2.0f;
|
|
||||||
posY -= ((mItemSize.y * mBackgroundRelativeScale) - mItemSize.y) / 2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
mRenderer->setMatrix(trans);
|
mRenderer->setMatrix(trans);
|
||||||
mRenderer->drawRect(posX, posY, sizeX, sizeY, mBackgroundColor, mBackgroundColorEnd,
|
mRenderer->drawRect(backgroundPos.x, backgroundPos.y, sizeX, sizeY, mBackgroundColor,
|
||||||
mBackgroundColorGradientHorizontal, opacity);
|
mBackgroundColorEnd, mBackgroundColorGradientHorizontal, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursorEntry && mSelectorLayer == SelectorLayer::MIDDLE)
|
if (cursorEntry && mSelectorLayer == SelectorLayer::MIDDLE)
|
||||||
selectorRenderFunc(it, scale, opacity, cursorEntry, lastCursorEntry);
|
selectorRenderFunc(it, itemPos, scale, originInwards, offsetInwards, opacity);
|
||||||
|
|
||||||
mEntries.at(*it).data.item->setScale(scale);
|
mEntries.at(*it).data.item->setScale(scale);
|
||||||
mEntries.at(*it).data.item->setOpacity(opacity);
|
mEntries.at(*it).data.item->setOpacity(opacity);
|
||||||
|
@ -857,7 +904,12 @@ template <typename T> void GridComponent<T>::render(const glm::mat4& parentTrans
|
||||||
mEntries.at(*it).data.item->setOpacity(1.0f);
|
mEntries.at(*it).data.item->setOpacity(1.0f);
|
||||||
|
|
||||||
if (cursorEntry && mSelectorLayer == SelectorLayer::TOP)
|
if (cursorEntry && mSelectorLayer == SelectorLayer::TOP)
|
||||||
selectorRenderFunc(it, scale, opacity, cursorEntry, lastCursorEntry);
|
selectorRenderFunc(it, itemPos, scale, originInwards, offsetInwards, opacity);
|
||||||
|
|
||||||
|
if (mScaleInwards && scale != 1.0f) {
|
||||||
|
mEntries.at(*it).data.item->setOrigin(0.5f, 0.5f);
|
||||||
|
mEntries.at(*it).data.item->setPosition(itemPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mRenderer->popClipRect();
|
mRenderer->popClipRect();
|
||||||
|
@ -959,6 +1011,9 @@ void GridComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
if (elem->has("imageRelativeScale"))
|
if (elem->has("imageRelativeScale"))
|
||||||
mImageRelativeScale = glm::clamp(elem->get<float>("imageRelativeScale"), 0.2f, 1.0f);
|
mImageRelativeScale = glm::clamp(elem->get<float>("imageRelativeScale"), 0.2f, 1.0f);
|
||||||
|
|
||||||
|
mScaleInwards =
|
||||||
|
(mItemScale > 1.0f && elem->has("scaleInwards") && elem->get<bool>("scaleInwards"));
|
||||||
|
|
||||||
if (elem->has("imageFit")) {
|
if (elem->has("imageFit")) {
|
||||||
const std::string& imageFit {elem->get<std::string>("imageFit")};
|
const std::string& imageFit {elem->get<std::string>("imageFit")};
|
||||||
if (imageFit == "contain") {
|
if (imageFit == "contain") {
|
||||||
|
|
Loading…
Reference in a new issue