mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 06:05:38 +00:00
Added reflections support to CarouselComponent.
This commit is contained in:
parent
79c61b2d8a
commit
1798b96cf8
|
@ -207,8 +207,13 @@ public:
|
||||||
mColorShift = color;
|
mColorShift = color;
|
||||||
mColorShiftEnd = color;
|
mColorShiftEnd = color;
|
||||||
}
|
}
|
||||||
|
virtual void setColorShiftEnd(unsigned int color) { mColorShiftEnd = color; }
|
||||||
virtual void setOriginalColor(unsigned int color) { mColorOriginalValue = color; }
|
virtual void setOriginalColor(unsigned int color) { mColorOriginalValue = color; }
|
||||||
virtual void setChangedColor(unsigned int color) { mColorChangedValue = color; }
|
virtual void setChangedColor(unsigned int color) { mColorChangedValue = color; }
|
||||||
|
virtual void setColorGradientHorizontal(bool horizontal) {}
|
||||||
|
virtual void setReflectionsFalloff(float falloff) {}
|
||||||
|
virtual void setFlipX(bool flip) {}
|
||||||
|
virtual void setFlipY(bool flip) {}
|
||||||
|
|
||||||
virtual void setImage(const std::string& path, bool tile = false) {}
|
virtual void setImage(const std::string& path, bool tile = false) {}
|
||||||
|
|
||||||
|
|
|
@ -262,6 +262,11 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
|
||||||
{"itemRotationOrigin", NORMALIZED_PAIR},
|
{"itemRotationOrigin", NORMALIZED_PAIR},
|
||||||
{"itemHorizontalAlignment", STRING},
|
{"itemHorizontalAlignment", STRING},
|
||||||
{"itemVerticalAlignment", STRING},
|
{"itemVerticalAlignment", STRING},
|
||||||
|
{"horizontalOffset", FLOAT},
|
||||||
|
{"verticalOffset", FLOAT},
|
||||||
|
{"reflections", BOOLEAN},
|
||||||
|
{"reflectionsOpacity", FLOAT},
|
||||||
|
{"reflectionsFalloff", FLOAT},
|
||||||
{"unfocusedItemOpacity", FLOAT},
|
{"unfocusedItemOpacity", FLOAT},
|
||||||
{"maxItemCount", FLOAT},
|
{"maxItemCount", FLOAT},
|
||||||
{"defaultLogo", PATH}, // For backward compatibility with legacy themes.
|
{"defaultLogo", PATH}, // For backward compatibility with legacy themes.
|
||||||
|
|
|
@ -40,6 +40,7 @@ ImageComponent::ImageComponent(bool forceLoad, bool dynamic)
|
||||||
, mColorShiftEnd {0xFFFFFFFF}
|
, mColorShiftEnd {0xFFFFFFFF}
|
||||||
, mColorGradientHorizontal {true}
|
, mColorGradientHorizontal {true}
|
||||||
, mFadeOpacity {0.0f}
|
, mFadeOpacity {0.0f}
|
||||||
|
, mReflectionsFalloff {0.0f}
|
||||||
, mFading {false}
|
, mFading {false}
|
||||||
, mForceLoad {forceLoad}
|
, mForceLoad {forceLoad}
|
||||||
, mDynamic {dynamic}
|
, mDynamic {dynamic}
|
||||||
|
@ -248,7 +249,7 @@ void ImageComponent::cropTransparentPadding(const float maxSizeX, const float ma
|
||||||
glm::ivec2 imageSize {mTexture.get()->getSize()};
|
glm::ivec2 imageSize {mTexture.get()->getSize()};
|
||||||
cimg_library::CImg<unsigned char> imageCImg(imageSize.x, imageSize.y, 1, 4, 0);
|
cimg_library::CImg<unsigned char> imageCImg(imageSize.x, imageSize.y, 1, 4, 0);
|
||||||
|
|
||||||
int paddingCoords[4] {};
|
int paddingCoords[4] {0, 0, 0, 0};
|
||||||
|
|
||||||
// We need to convert our RGBA data to the CImg internal format as CImg does not interleave
|
// We need to convert our RGBA data to the CImg internal format as CImg does not interleave
|
||||||
// the pixels (as in RGBARGBARGBA).
|
// the pixels (as in RGBARGBARGBA).
|
||||||
|
@ -377,7 +378,7 @@ void ImageComponent::updateVertices()
|
||||||
|
|
||||||
void ImageComponent::updateColors()
|
void ImageComponent::updateColors()
|
||||||
{
|
{
|
||||||
const float opacity = (mOpacity * (mFading ? mFadeOpacity : 1.0f));
|
const float opacity {mOpacity * (mFading ? mFadeOpacity : 1.0f)};
|
||||||
const unsigned int color {(mColorShift & 0xFFFFFF00) |
|
const unsigned int color {(mColorShift & 0xFFFFFF00) |
|
||||||
static_cast<unsigned char>((mColorShift & 0xFF) * opacity)};
|
static_cast<unsigned char>((mColorShift & 0xFF) * opacity)};
|
||||||
const unsigned int colorEnd {(mColorShiftEnd & 0xFFFFFF00) |
|
const unsigned int colorEnd {(mColorShiftEnd & 0xFFFFFF00) |
|
||||||
|
@ -421,6 +422,7 @@ void ImageComponent::render(const glm::mat4& parentTrans)
|
||||||
mVertices->saturation = mSaturation * mThemeSaturation;
|
mVertices->saturation = mSaturation * mThemeSaturation;
|
||||||
mVertices->opacity = mThemeOpacity;
|
mVertices->opacity = mThemeOpacity;
|
||||||
mVertices->dimming = mDimming;
|
mVertices->dimming = mDimming;
|
||||||
|
mVertices->reflectionsFalloff = mReflectionsFalloff;
|
||||||
|
|
||||||
mRenderer->drawTriangleStrips(&mVertices[0], 4);
|
mRenderer->drawTriangleStrips(&mVertices[0], 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,8 @@ public:
|
||||||
|
|
||||||
// Multiply all pixels in the image by this color when rendering.
|
// Multiply all pixels in the image by this color when rendering.
|
||||||
void setColorShift(unsigned int color) override;
|
void setColorShift(unsigned int color) override;
|
||||||
void setColorShiftEnd(unsigned int color);
|
void setColorShiftEnd(unsigned int color) override;
|
||||||
void setColorGradientHorizontal(bool horizontal);
|
void setColorGradientHorizontal(bool horizontal) override;
|
||||||
|
|
||||||
unsigned int getColorShift() const override { return mColorShift; }
|
unsigned int getColorShift() const override { return mColorShift; }
|
||||||
|
|
||||||
|
@ -75,8 +75,9 @@ public:
|
||||||
void setSaturation(float saturation) override;
|
void setSaturation(float saturation) override;
|
||||||
void setDimming(float dimming) override;
|
void setDimming(float dimming) override;
|
||||||
|
|
||||||
void setFlipX(bool flip); // Mirror on the X axis.
|
void setReflectionsFalloff(float falloff) override { mReflectionsFalloff = falloff; }
|
||||||
void setFlipY(bool flip); // Mirror on the Y axis.
|
void setFlipX(bool flip) override; // Mirror on the X axis.
|
||||||
|
void setFlipY(bool flip) override; // Mirror on the Y axis.
|
||||||
|
|
||||||
// Flag indicating if rotation should be based on target size vs. actual size.
|
// Flag indicating if rotation should be based on target size vs. actual size.
|
||||||
void setRotateByTargetSize(bool rotate) { mRotateByTargetSize = rotate; }
|
void setRotateByTargetSize(bool rotate) { mRotateByTargetSize = rotate; }
|
||||||
|
@ -129,6 +130,7 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<TextureResource> mTexture;
|
std::shared_ptr<TextureResource> mTexture;
|
||||||
float mFadeOpacity;
|
float mFadeOpacity;
|
||||||
|
float mReflectionsFalloff;
|
||||||
bool mFading;
|
bool mFading;
|
||||||
bool mForceLoad;
|
bool mForceLoad;
|
||||||
bool mDynamic;
|
bool mDynamic;
|
||||||
|
|
|
@ -117,6 +117,7 @@ private:
|
||||||
CarouselType mType;
|
CarouselType mType;
|
||||||
std::string mItemType;
|
std::string mItemType;
|
||||||
std::string mDefaultItem;
|
std::string mDefaultItem;
|
||||||
|
bool mLegacyMode;
|
||||||
std::shared_ptr<Font> mFont;
|
std::shared_ptr<Font> mFont;
|
||||||
unsigned int mTextColor;
|
unsigned int mTextColor;
|
||||||
unsigned int mTextBackgroundColor;
|
unsigned int mTextBackgroundColor;
|
||||||
|
@ -133,6 +134,11 @@ private:
|
||||||
unsigned int mCarouselColor;
|
unsigned int mCarouselColor;
|
||||||
unsigned int mCarouselColorEnd;
|
unsigned int mCarouselColorEnd;
|
||||||
bool mColorGradientHorizontal;
|
bool mColorGradientHorizontal;
|
||||||
|
bool mReflections;
|
||||||
|
float mReflectionsOpacity;
|
||||||
|
float mReflectionsFalloff;
|
||||||
|
float mHorizontalOffset;
|
||||||
|
float mVerticalOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -146,6 +152,7 @@ CarouselComponent<T>::CarouselComponent()
|
||||||
, mPreviousScrollVelocity {0}
|
, mPreviousScrollVelocity {0}
|
||||||
, mTriggerJump {false}
|
, mTriggerJump {false}
|
||||||
, mType {CarouselType::HORIZONTAL}
|
, mType {CarouselType::HORIZONTAL}
|
||||||
|
, mLegacyMode {false}
|
||||||
, mFont {Font::get(FONT_SIZE_LARGE)}
|
, mFont {Font::get(FONT_SIZE_LARGE)}
|
||||||
, mTextColor {0x000000FF}
|
, mTextColor {0x000000FF}
|
||||||
, mTextBackgroundColor {0xFFFFFF00}
|
, mTextBackgroundColor {0xFFFFFF00}
|
||||||
|
@ -161,6 +168,11 @@ CarouselComponent<T>::CarouselComponent()
|
||||||
, mCarouselColor {0}
|
, mCarouselColor {0}
|
||||||
, mCarouselColorEnd {0}
|
, mCarouselColorEnd {0}
|
||||||
, mColorGradientHorizontal {true}
|
, mColorGradientHorizontal {true}
|
||||||
|
, mReflections {false}
|
||||||
|
, mReflectionsOpacity {0.5f}
|
||||||
|
, mReflectionsFalloff {1.0f}
|
||||||
|
, mHorizontalOffset {0.0f}
|
||||||
|
, mVerticalOffset {0.0f}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +195,7 @@ void CarouselComponent<T>::addEntry(Entry& entry, const std::shared_ptr<ThemeDat
|
||||||
(!defaultPath.empty() && ResourceManager::getInstance().fileExists(defaultPath))) {
|
(!defaultPath.empty() && ResourceManager::getInstance().fileExists(defaultPath))) {
|
||||||
auto item = std::make_shared<ImageComponent>(false, false);
|
auto item = std::make_shared<ImageComponent>(false, false);
|
||||||
item->setLinearInterpolation(true);
|
item->setLinearInterpolation(true);
|
||||||
item->setMaxSize(glm::round(mItemSize * mItemScale));
|
item->setMaxSize(mItemSize * mItemScale);
|
||||||
item->applyTheme(theme, "system", "image_logo",
|
item->applyTheme(theme, "system", "image_logo",
|
||||||
ThemeFlags::PATH | ThemeFlags::COLOR);
|
ThemeFlags::PATH | ThemeFlags::COLOR);
|
||||||
item->setRotateByTargetSize(true);
|
item->setRotateByTargetSize(true);
|
||||||
|
@ -197,7 +209,7 @@ void CarouselComponent<T>::addEntry(Entry& entry, const std::shared_ptr<ThemeDat
|
||||||
auto item = std::make_shared<ImageComponent>(false, false);
|
auto item = std::make_shared<ImageComponent>(false, false);
|
||||||
item->setLinearInterpolation(true);
|
item->setLinearInterpolation(true);
|
||||||
item->setImage(entry.data.itemPath);
|
item->setImage(entry.data.itemPath);
|
||||||
item->setMaxSize(glm::round(mItemSize * mItemScale));
|
item->setMaxSize(mItemSize * mItemScale);
|
||||||
item->applyTheme(theme, "system", "", ThemeFlags::ALL);
|
item->applyTheme(theme, "system", "", ThemeFlags::ALL);
|
||||||
item->setRotateByTargetSize(true);
|
item->setRotateByTargetSize(true);
|
||||||
entry.data.item = item;
|
entry.data.item = item;
|
||||||
|
@ -207,7 +219,7 @@ void CarouselComponent<T>::addEntry(Entry& entry, const std::shared_ptr<ThemeDat
|
||||||
auto defaultItem = std::make_shared<ImageComponent>(false, false);
|
auto defaultItem = std::make_shared<ImageComponent>(false, false);
|
||||||
defaultItem->setLinearInterpolation(true);
|
defaultItem->setLinearInterpolation(true);
|
||||||
defaultItem->setImage(entry.data.defaultItemPath);
|
defaultItem->setImage(entry.data.defaultItemPath);
|
||||||
defaultItem->setMaxSize(glm::round(mItemSize * mItemScale));
|
defaultItem->setMaxSize(mItemSize * mItemScale);
|
||||||
defaultItem->applyTheme(theme, "system", "", ThemeFlags::ALL);
|
defaultItem->applyTheme(theme, "system", "", ThemeFlags::ALL);
|
||||||
defaultItem->setRotateByTargetSize(true);
|
defaultItem->setRotateByTargetSize(true);
|
||||||
entry.data.item = defaultItem;
|
entry.data.item = defaultItem;
|
||||||
|
@ -403,37 +415,60 @@ template <typename T> void CarouselComponent<T>::render(const glm::mat4& parentT
|
||||||
float xOff {0.0f};
|
float xOff {0.0f};
|
||||||
float yOff {0.0f};
|
float yOff {0.0f};
|
||||||
|
|
||||||
switch (mType) {
|
if (mType == CarouselType::HORIZONTAL_WHEEL || mType == CarouselType::VERTICAL_WHEEL) {
|
||||||
case CarouselType::HORIZONTAL_WHEEL:
|
xOff = (mSize.x - mItemSize.x) / 2.0f - (mEntryCamOffset * itemSpacing.y);
|
||||||
case CarouselType::VERTICAL_WHEEL:
|
yOff = (mSize.y - mItemSize.y) / 2.0f;
|
||||||
xOff = std::round((mSize.x - mItemSize.x) / 2.0f - (mEntryCamOffset * itemSpacing.y));
|
}
|
||||||
yOff = (mSize.y - mItemSize.y) / 2.0f;
|
else if (mType == CarouselType::VERTICAL) {
|
||||||
break;
|
itemSpacing.y = ((mSize.y - (mItemSize.y * mMaxItemCount)) / (mMaxItemCount)) + mItemSize.y;
|
||||||
case CarouselType::VERTICAL:
|
yOff = (mSize.y - mItemSize.y) / 2.0f - (mEntryCamOffset * itemSpacing.y);
|
||||||
itemSpacing.y =
|
if (mItemHorizontalAlignment == ALIGN_LEFT) {
|
||||||
((mSize.y - (mItemSize.y * mMaxItemCount)) / (mMaxItemCount)) + mItemSize.y;
|
if (mLegacyMode)
|
||||||
yOff = (mSize.y - mItemSize.y) / 2.0f - (mEntryCamOffset * itemSpacing.y);
|
|
||||||
if (mItemHorizontalAlignment == ALIGN_LEFT)
|
|
||||||
xOff = mItemSize.x / 10.0f;
|
xOff = mItemSize.x / 10.0f;
|
||||||
else if (mItemHorizontalAlignment == ALIGN_RIGHT)
|
|
||||||
xOff = mSize.x - (mItemSize.x * 1.1f);
|
|
||||||
else
|
else
|
||||||
xOff = (mSize.x - mItemSize.x) / 2.0f;
|
xOff = 0.0f;
|
||||||
break;
|
}
|
||||||
case CarouselType::HORIZONTAL:
|
else if (mItemHorizontalAlignment == ALIGN_RIGHT) {
|
||||||
default:
|
if (mLegacyMode)
|
||||||
itemSpacing.x =
|
xOff = mSize.x - mItemSize.x * 1.1f;
|
||||||
((mSize.x - (mItemSize.x * mMaxItemCount)) / (mMaxItemCount)) + mItemSize.x;
|
else
|
||||||
xOff = std::round((mSize.x - mItemSize.x) / 2.0f - (mEntryCamOffset * itemSpacing.x));
|
xOff = mSize.x - mItemSize.x;
|
||||||
if (mItemVerticalAlignment == ALIGN_TOP)
|
}
|
||||||
|
else {
|
||||||
|
xOff = (mSize.x - mItemSize.x) / 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // HORIZONTAL.
|
||||||
|
itemSpacing.x = ((mSize.x - (mItemSize.x * mMaxItemCount)) / (mMaxItemCount)) + mItemSize.x;
|
||||||
|
xOff = (mSize.x - mItemSize.x) / 2.0f - (mEntryCamOffset * itemSpacing.x);
|
||||||
|
if (mItemVerticalAlignment == ALIGN_TOP) {
|
||||||
|
if (mLegacyMode)
|
||||||
yOff = mItemSize.y / 10.0f;
|
yOff = mItemSize.y / 10.0f;
|
||||||
else if (mItemVerticalAlignment == ALIGN_BOTTOM)
|
else
|
||||||
|
yOff = 0.0f;
|
||||||
|
}
|
||||||
|
else if (mItemVerticalAlignment == ALIGN_BOTTOM) {
|
||||||
|
if (mLegacyMode)
|
||||||
yOff = mSize.y - (mItemSize.y * 1.1f);
|
yOff = mSize.y - (mItemSize.y * 1.1f);
|
||||||
else
|
else
|
||||||
|
yOff = mSize.y - mItemSize.y - (mReflections ? ((mItemSize.y * mItemScale)) : 0.0f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (mLegacyMode)
|
||||||
yOff = (mSize.y - mItemSize.y) / 2.0f;
|
yOff = (mSize.y - mItemSize.y) / 2.0f;
|
||||||
break;
|
else
|
||||||
|
yOff = (mSize.y - (mItemSize.y * (mReflections ? 2.0f : 1.0f))) / 2.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mLegacyMode) {
|
||||||
|
xOff += mSize.x * mHorizontalOffset;
|
||||||
|
yOff += mSize.y * mVerticalOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
xOff = std::round(xOff);
|
||||||
|
yOff = std::round(yOff);
|
||||||
|
|
||||||
int center {static_cast<int>(mEntryCamOffset)};
|
int center {static_cast<int>(mEntryCamOffset)};
|
||||||
int itemInclusion {static_cast<int>(std::ceil(mMaxItemCount / 2.0f))};
|
int itemInclusion {static_cast<int>(std::ceil(mMaxItemCount / 2.0f))};
|
||||||
bool singleEntry {mEntries.size() == 1};
|
bool singleEntry {mEntries.size() == 1};
|
||||||
|
@ -441,28 +476,27 @@ template <typename T> void CarouselComponent<T>::render(const glm::mat4& parentT
|
||||||
for (int i = center - itemInclusion; i < center + itemInclusion + 2; ++i) {
|
for (int i = center - itemInclusion; i < center + itemInclusion + 2; ++i) {
|
||||||
int index {i};
|
int index {i};
|
||||||
|
|
||||||
// If there is only a single entry, then only render the item once (in the center).
|
|
||||||
if (singleEntry) {
|
|
||||||
mEntries.at(0).data.item->render(
|
|
||||||
glm::translate(carouselTrans, glm::vec3 {0 + xOff, 0 + yOff, 0.0f}));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (index < 0)
|
while (index < 0)
|
||||||
index += static_cast<int>(mEntries.size());
|
index += static_cast<int>(mEntries.size());
|
||||||
while (index >= static_cast<int>(mEntries.size()))
|
while (index >= static_cast<int>(mEntries.size()))
|
||||||
index -= static_cast<int>(mEntries.size());
|
index -= static_cast<int>(mEntries.size());
|
||||||
|
|
||||||
glm::mat4 itemTrans {carouselTrans};
|
|
||||||
itemTrans = glm::translate(
|
|
||||||
itemTrans, glm::vec3 {i * itemSpacing.x + xOff, i * itemSpacing.y + yOff, 0.0f});
|
|
||||||
|
|
||||||
float distance {i - mEntryCamOffset};
|
float distance {i - mEntryCamOffset};
|
||||||
|
|
||||||
|
if (singleEntry)
|
||||||
|
distance = 0.0f;
|
||||||
|
|
||||||
float scale {1.0f + ((mItemScale - 1.0f) * (1.0f - fabsf(distance)))};
|
float scale {1.0f + ((mItemScale - 1.0f) * (1.0f - fabsf(distance)))};
|
||||||
scale = std::min(mItemScale, std::max(1.0f, scale));
|
scale = std::min(mItemScale, std::max(1.0f, scale));
|
||||||
scale /= mItemScale;
|
scale /= mItemScale;
|
||||||
|
|
||||||
|
glm::mat4 itemTrans {carouselTrans};
|
||||||
|
if (singleEntry)
|
||||||
|
itemTrans = glm::translate(carouselTrans, glm::vec3 {xOff, yOff, 0.0f});
|
||||||
|
else
|
||||||
|
itemTrans = glm::translate(
|
||||||
|
itemTrans, glm::vec3 {i * itemSpacing.x + xOff, i * itemSpacing.y + yOff, 0.0f});
|
||||||
|
|
||||||
float opacity {0.0f};
|
float opacity {0.0f};
|
||||||
|
|
||||||
if (distance == 0.0f || mUnfocusedItemOpacity == 1.0f) {
|
if (distance == 0.0f || mUnfocusedItemOpacity == 1.0f) {
|
||||||
|
@ -486,17 +520,33 @@ template <typename T> void CarouselComponent<T>::render(const glm::mat4& parentT
|
||||||
comp->setRotationOrigin(mItemRotationOrigin);
|
comp->setRotationOrigin(mItemRotationOrigin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When running at lower resolutions, prevent the scale-down to go all the way to
|
|
||||||
// the minimum value. This avoids potential single-pixel alignment issues when the
|
|
||||||
// item can't be vertically placed exactly in the middle of the carousel. Although
|
|
||||||
// the problem theoretically exists at all resolutions, it's not visble at around
|
|
||||||
// 1080p and above.
|
|
||||||
if (std::min(Renderer::getScreenWidth(), Renderer::getScreenHeight()) < 1080.0f)
|
|
||||||
scale = glm::clamp(scale, 1.0f / mItemScale + 0.01f, 1.0f);
|
|
||||||
|
|
||||||
comp->setScale(scale);
|
comp->setScale(scale);
|
||||||
comp->setOpacity(opacity);
|
comp->setOpacity(opacity);
|
||||||
comp->render(itemTrans);
|
comp->render(itemTrans);
|
||||||
|
|
||||||
|
// Don't attempt to add reflections for text entries.
|
||||||
|
if (mReflections && (mEntries.at(index).data.itemPath != "" ||
|
||||||
|
mEntries.at(index).data.defaultItemPath != "")) {
|
||||||
|
itemTrans =
|
||||||
|
glm::translate(itemTrans, glm::vec3 {0.0f, comp->getSize().y * scale, 0.0f});
|
||||||
|
const unsigned int colorShift {comp->getColorShift()};
|
||||||
|
comp->setColorGradientHorizontal(false);
|
||||||
|
comp->setColorShift(0xFFFFFF00 | static_cast<int>(mReflectionsOpacity * 255.0f));
|
||||||
|
float falloff {glm::clamp(mReflectionsFalloff, 0.0f, 1.0f)};
|
||||||
|
falloff = mReflectionsOpacity * (1.0f - falloff);
|
||||||
|
comp->setColorShiftEnd(0xFFFFFF00 | static_cast<int>(falloff * 255.0f));
|
||||||
|
// "Extra" falloff as a value of 1.0 already fades the image completely.
|
||||||
|
if (mReflectionsFalloff > 1.0f)
|
||||||
|
comp->setReflectionsFalloff(mReflectionsFalloff - 1.0f);
|
||||||
|
comp->setFlipY(true);
|
||||||
|
comp->render(itemTrans);
|
||||||
|
comp->setFlipY(false);
|
||||||
|
comp->setColorShift(colorShift);
|
||||||
|
comp->setReflectionsFalloff(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (singleEntry)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
mRenderer->popClipRect();
|
mRenderer->popClipRect();
|
||||||
}
|
}
|
||||||
|
@ -522,6 +572,8 @@ void CarouselComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
if (!elem)
|
if (!elem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
mLegacyMode = theme->isLegacyTheme();
|
||||||
|
|
||||||
if (elem->has("type")) {
|
if (elem->has("type")) {
|
||||||
const std::string type {elem->get<std::string>("type")};
|
const std::string type {elem->get<std::string>("type")};
|
||||||
if (type == "horizontal") {
|
if (type == "horizontal") {
|
||||||
|
@ -567,7 +619,7 @@ void CarouselComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!theme->isLegacyTheme()) {
|
if (!mLegacyMode) {
|
||||||
if (elem->has("itemScale"))
|
if (elem->has("itemScale"))
|
||||||
mItemScale = glm::clamp(elem->get<float>("itemScale"), 0.5f, 3.0f);
|
mItemScale = glm::clamp(elem->get<float>("itemScale"), 0.5f, 3.0f);
|
||||||
if (elem->has("itemSize")) {
|
if (elem->has("itemSize")) {
|
||||||
|
@ -633,76 +685,99 @@ void CarouselComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elem->has("horizontalOffset"))
|
||||||
|
mHorizontalOffset = glm::clamp(elem->get<float>("horizontalOffset"), -1.0f, 1.0f);
|
||||||
|
|
||||||
|
if (elem->has("verticalOffset"))
|
||||||
|
mVerticalOffset = glm::clamp(elem->get<float>("verticalOffset"), -1.0f, 1.0f);
|
||||||
|
|
||||||
|
if (elem->has("reflections") && elem->get<bool>("reflections")) {
|
||||||
|
if (mType == CarouselType::HORIZONTAL) {
|
||||||
|
mReflections = elem->get<bool>("reflections");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property "
|
||||||
|
"<reflections> only supported for horizontal carousel type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem->has("reflectionsOpacity"))
|
||||||
|
mReflectionsOpacity = glm::clamp(elem->get<float>("reflectionsOpacity"), 0.1f, 1.0f);
|
||||||
|
|
||||||
|
if (elem->has("reflectionsFalloff"))
|
||||||
|
mReflectionsFalloff = glm::clamp(elem->get<float>("reflectionsFalloff"), 0.0f, 5.0f);
|
||||||
|
|
||||||
if (elem->has("unfocusedItemOpacity"))
|
if (elem->has("unfocusedItemOpacity"))
|
||||||
mUnfocusedItemOpacity =
|
mUnfocusedItemOpacity =
|
||||||
glm::clamp(elem->get<float>("unfocusedItemOpacity"), 0.1f, 1.0f);
|
glm::clamp(elem->get<float>("unfocusedItemOpacity"), 0.1f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start of legacy themes only section.
|
// Legacy themes.
|
||||||
|
if (mLegacyMode) {
|
||||||
|
if (elem->has("logoScale"))
|
||||||
|
mItemScale = glm::clamp(elem->get<float>("logoScale"), 0.5f, 3.0f);
|
||||||
|
if (elem->has("logoSize")) {
|
||||||
|
// Keep size within a 0.05 and 1.0 multiple of the screen size.
|
||||||
|
glm::vec2 itemSize {elem->get<glm::vec2>("logoSize")};
|
||||||
|
if (std::max(itemSize.x, itemSize.y) > 1.0f) {
|
||||||
|
itemSize /= std::max(itemSize.x, itemSize.y);
|
||||||
|
}
|
||||||
|
else if (std::min(itemSize.x, itemSize.y) < 0.005f) {
|
||||||
|
float ratio {std::min(itemSize.x, itemSize.y) / 0.005f};
|
||||||
|
itemSize /= ratio;
|
||||||
|
// Just an extra precaution if a crazy ratio was used.
|
||||||
|
itemSize.x = glm::clamp(itemSize.x, 0.005f, 1.0f);
|
||||||
|
itemSize.y = glm::clamp(itemSize.y, 0.005f, 1.0f);
|
||||||
|
}
|
||||||
|
mItemSize =
|
||||||
|
itemSize * glm::vec2(Renderer::getScreenWidth(), Renderer::getScreenHeight());
|
||||||
|
}
|
||||||
|
|
||||||
if (elem->has("logoScale"))
|
if (elem->has("maxLogoCount")) {
|
||||||
mItemScale = glm::clamp(elem->get<float>("logoScale"), 0.5f, 3.0f);
|
if (theme->isLegacyTheme())
|
||||||
if (elem->has("logoSize")) {
|
mMaxItemCount =
|
||||||
// Keep size within a 0.05 and 1.0 multiple of the screen size.
|
std::ceil(glm::clamp(elem->get<float>("maxLogoCount"), 0.5f, 30.0f));
|
||||||
glm::vec2 itemSize {elem->get<glm::vec2>("logoSize")};
|
else
|
||||||
if (std::max(itemSize.x, itemSize.y) > 1.0f) {
|
mMaxItemCount = glm::clamp(elem->get<float>("maxLogoCount"), 0.5f, 30.0f);
|
||||||
itemSize /= std::max(itemSize.x, itemSize.y);
|
|
||||||
}
|
}
|
||||||
else if (std::min(itemSize.x, itemSize.y) < 0.005f) {
|
|
||||||
float ratio {std::min(itemSize.x, itemSize.y) / 0.005f};
|
|
||||||
itemSize /= ratio;
|
|
||||||
// Just an extra precaution if a crazy ratio was used.
|
|
||||||
itemSize.x = glm::clamp(itemSize.x, 0.005f, 1.0f);
|
|
||||||
itemSize.y = glm::clamp(itemSize.y, 0.005f, 1.0f);
|
|
||||||
}
|
|
||||||
mItemSize = itemSize * glm::vec2(Renderer::getScreenWidth(), Renderer::getScreenHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elem->has("maxLogoCount")) {
|
if (elem->has("logoRotation"))
|
||||||
if (theme->isLegacyTheme())
|
mItemRotation = elem->get<float>("logoRotation");
|
||||||
mMaxItemCount = std::ceil(glm::clamp(elem->get<float>("maxLogoCount"), 0.5f, 30.0f));
|
if (elem->has("logoRotationOrigin"))
|
||||||
else
|
mItemRotationOrigin = elem->get<glm::vec2>("logoRotationOrigin");
|
||||||
mMaxItemCount = glm::clamp(elem->get<float>("maxLogoCount"), 0.5f, 30.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elem->has("logoRotation"))
|
if (elem->has("logoAlignment")) {
|
||||||
mItemRotation = elem->get<float>("logoRotation");
|
const std::string alignment {elem->get<std::string>("logoAlignment")};
|
||||||
if (elem->has("logoRotationOrigin"))
|
if (alignment == "left" && mType != CarouselType::HORIZONTAL) {
|
||||||
mItemRotationOrigin = elem->get<glm::vec2>("logoRotationOrigin");
|
mItemHorizontalAlignment = ALIGN_LEFT;
|
||||||
|
mItemVerticalAlignment = ALIGN_CENTER;
|
||||||
if (elem->has("logoAlignment")) {
|
}
|
||||||
const std::string alignment {elem->get<std::string>("logoAlignment")};
|
else if (alignment == "right" && mType != CarouselType::HORIZONTAL) {
|
||||||
if (alignment == "left" && mType != CarouselType::HORIZONTAL) {
|
mItemHorizontalAlignment = ALIGN_RIGHT;
|
||||||
mItemHorizontalAlignment = ALIGN_LEFT;
|
mItemVerticalAlignment = ALIGN_CENTER;
|
||||||
mItemVerticalAlignment = ALIGN_CENTER;
|
}
|
||||||
}
|
else if (alignment == "top" && mType != CarouselType::VERTICAL) {
|
||||||
else if (alignment == "right" && mType != CarouselType::HORIZONTAL) {
|
mItemVerticalAlignment = ALIGN_TOP;
|
||||||
mItemHorizontalAlignment = ALIGN_RIGHT;
|
mItemHorizontalAlignment = ALIGN_CENTER;
|
||||||
mItemVerticalAlignment = ALIGN_CENTER;
|
}
|
||||||
}
|
else if (alignment == "bottom" && mType != CarouselType::VERTICAL) {
|
||||||
else if (alignment == "top" && mType != CarouselType::VERTICAL) {
|
mItemVerticalAlignment = ALIGN_BOTTOM;
|
||||||
mItemVerticalAlignment = ALIGN_TOP;
|
mItemHorizontalAlignment = ALIGN_CENTER;
|
||||||
mItemHorizontalAlignment = ALIGN_CENTER;
|
}
|
||||||
}
|
else if (alignment == "center") {
|
||||||
else if (alignment == "bottom" && mType != CarouselType::VERTICAL) {
|
mItemHorizontalAlignment = ALIGN_CENTER;
|
||||||
mItemVerticalAlignment = ALIGN_BOTTOM;
|
mItemVerticalAlignment = ALIGN_CENTER;
|
||||||
mItemHorizontalAlignment = ALIGN_CENTER;
|
}
|
||||||
}
|
else {
|
||||||
else if (alignment == "center") {
|
LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property "
|
||||||
mItemHorizontalAlignment = ALIGN_CENTER;
|
"<logoAlignment> defined as \""
|
||||||
mItemVerticalAlignment = ALIGN_CENTER;
|
<< alignment << "\"";
|
||||||
}
|
mItemHorizontalAlignment = ALIGN_CENTER;
|
||||||
else {
|
mItemVerticalAlignment = ALIGN_CENTER;
|
||||||
LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property "
|
}
|
||||||
"<logoAlignment> defined as \""
|
|
||||||
<< alignment << "\"";
|
|
||||||
mItemHorizontalAlignment = ALIGN_CENTER;
|
|
||||||
mItemVerticalAlignment = ALIGN_CENTER;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of legacy theme section.
|
|
||||||
|
|
||||||
mFont = Font::getFromTheme(elem, properties, mFont);
|
mFont = Font::getFromTheme(elem, properties, mFont);
|
||||||
|
|
||||||
if (elem->has("textColor"))
|
if (elem->has("textColor"))
|
||||||
|
|
|
@ -62,6 +62,7 @@ public:
|
||||||
float opacity;
|
float opacity;
|
||||||
float saturation;
|
float saturation;
|
||||||
float dimming;
|
float dimming;
|
||||||
|
float reflectionsFalloff;
|
||||||
unsigned int shaders;
|
unsigned int shaders;
|
||||||
unsigned int shaderFlags;
|
unsigned int shaderFlags;
|
||||||
|
|
||||||
|
@ -69,6 +70,7 @@ public:
|
||||||
: opacity {1.0f}
|
: opacity {1.0f}
|
||||||
, saturation {1.0f}
|
, saturation {1.0f}
|
||||||
, dimming {1.0f}
|
, dimming {1.0f}
|
||||||
|
, reflectionsFalloff {0.0f}
|
||||||
, shaders {0}
|
, shaders {0}
|
||||||
, shaderFlags {0}
|
, shaderFlags {0}
|
||||||
{
|
{
|
||||||
|
@ -81,6 +83,7 @@ public:
|
||||||
, opacity {1.0f}
|
, opacity {1.0f}
|
||||||
, saturation {1.0f}
|
, saturation {1.0f}
|
||||||
, dimming {1.0f}
|
, dimming {1.0f}
|
||||||
|
, reflectionsFalloff {0.0f}
|
||||||
, shaders {0}
|
, shaders {0}
|
||||||
, shaderFlags {0}
|
, shaderFlags {0}
|
||||||
{
|
{
|
||||||
|
|
|
@ -277,8 +277,8 @@ void RendererOpenGL::destroyContext()
|
||||||
|
|
||||||
void RendererOpenGL::setMatrix(const glm::mat4& matrix)
|
void RendererOpenGL::setMatrix(const glm::mat4& matrix)
|
||||||
{
|
{
|
||||||
mTrans = matrix;
|
// Set matrix for use with shader.
|
||||||
mTrans = getProjectionMatrix() * mTrans;
|
mTrans = getProjectionMatrix() * matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::setScissor(const Rect& scissor)
|
void RendererOpenGL::setScissor(const Rect& scissor)
|
||||||
|
@ -421,6 +421,7 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices,
|
||||||
mCoreShader->setOpacity(vertices->opacity);
|
mCoreShader->setOpacity(vertices->opacity);
|
||||||
mCoreShader->setSaturation(vertices->saturation);
|
mCoreShader->setSaturation(vertices->saturation);
|
||||||
mCoreShader->setDimming(vertices->dimming);
|
mCoreShader->setDimming(vertices->dimming);
|
||||||
|
mCoreShader->setReflectionsFalloff(vertices->reflectionsFalloff);
|
||||||
mCoreShader->setFlags(vertices->shaderFlags);
|
mCoreShader->setFlags(vertices->shaderFlags);
|
||||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
|
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
|
||||||
mLastShader = mCoreShader;
|
mLastShader = mCoreShader;
|
||||||
|
|
|
@ -22,6 +22,7 @@ ShaderOpenGL::ShaderOpenGL()
|
||||||
, mShaderOpacity {0}
|
, mShaderOpacity {0}
|
||||||
, mShaderSaturation {0}
|
, mShaderSaturation {0}
|
||||||
, mShaderDimming {0}
|
, mShaderDimming {0}
|
||||||
|
, mShaderReflectionsFalloff {0}
|
||||||
, mShaderFlags {0}
|
, mShaderFlags {0}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -123,6 +124,7 @@ void ShaderOpenGL::getVariableLocations(GLuint programID)
|
||||||
mShaderOpacity = glGetUniformLocation(mProgramID, "opacity");
|
mShaderOpacity = glGetUniformLocation(mProgramID, "opacity");
|
||||||
mShaderSaturation = glGetUniformLocation(mProgramID, "saturation");
|
mShaderSaturation = glGetUniformLocation(mProgramID, "saturation");
|
||||||
mShaderDimming = glGetUniformLocation(mProgramID, "dimming");
|
mShaderDimming = glGetUniformLocation(mProgramID, "dimming");
|
||||||
|
mShaderReflectionsFalloff = glGetUniformLocation(mProgramID, "reflectionsFalloff");
|
||||||
mShaderFlags = glGetUniformLocation(mProgramID, "shaderFlags");
|
mShaderFlags = glGetUniformLocation(mProgramID, "shaderFlags");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +176,12 @@ void ShaderOpenGL::setDimming(GLfloat dimming)
|
||||||
GL_CHECK_ERROR(glUniform1f(mShaderDimming, dimming));
|
GL_CHECK_ERROR(glUniform1f(mShaderDimming, dimming));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderOpenGL::setReflectionsFalloff(GLfloat falloff)
|
||||||
|
{
|
||||||
|
if (mShaderReflectionsFalloff != -1)
|
||||||
|
GL_CHECK_ERROR(glUniform1f(mShaderReflectionsFalloff, falloff));
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderOpenGL::setFlags(GLuint flags)
|
void ShaderOpenGL::setFlags(GLuint flags)
|
||||||
{
|
{
|
||||||
if (mShaderFlags != -1)
|
if (mShaderFlags != -1)
|
||||||
|
|
|
@ -71,6 +71,7 @@ public:
|
||||||
void setOpacity(GLfloat opacity);
|
void setOpacity(GLfloat opacity);
|
||||||
void setSaturation(GLfloat saturation);
|
void setSaturation(GLfloat saturation);
|
||||||
void setDimming(GLfloat dimming);
|
void setDimming(GLfloat dimming);
|
||||||
|
void setReflectionsFalloff(GLfloat falloff);
|
||||||
void setFlags(GLuint flags);
|
void setFlags(GLuint flags);
|
||||||
// Sets the shader program to use the loaded shaders.
|
// Sets the shader program to use the loaded shaders.
|
||||||
void activateShaders();
|
void activateShaders();
|
||||||
|
@ -95,6 +96,7 @@ private:
|
||||||
GLint mShaderOpacity;
|
GLint mShaderOpacity;
|
||||||
GLint mShaderSaturation;
|
GLint mShaderSaturation;
|
||||||
GLint mShaderDimming;
|
GLint mShaderDimming;
|
||||||
|
GLint mShaderReflectionsFalloff;
|
||||||
GLint mShaderFlags;
|
GLint mShaderFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ in vec2 texCoord;
|
||||||
uniform float opacity;
|
uniform float opacity;
|
||||||
uniform float saturation;
|
uniform float saturation;
|
||||||
uniform float dimming;
|
uniform float dimming;
|
||||||
|
uniform float reflectionsFalloff;
|
||||||
uniform uint shaderFlags;
|
uniform uint shaderFlags;
|
||||||
|
|
||||||
uniform sampler2D textureSampler;
|
uniform sampler2D textureSampler;
|
||||||
|
@ -83,6 +84,10 @@ void main()
|
||||||
if (0u != (shaderFlags & 1u))
|
if (0u != (shaderFlags & 1u))
|
||||||
sampledColor = sampledColor.bgra;
|
sampledColor = sampledColor.bgra;
|
||||||
|
|
||||||
|
// Reflections falloff.
|
||||||
|
if (reflectionsFalloff > 0.0)
|
||||||
|
sampledColor.a = mix(sampledColor.a, sampledColor.a - reflectionsFalloff, texCoord.y);
|
||||||
|
|
||||||
FragColor = sampledColor;
|
FragColor = sampledColor;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue