mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 23:55:38 +00:00
Refactored RatingComponent to improve rendering accuracy and performance.
This commit is contained in:
parent
077c6abf3e
commit
48a9571609
|
@ -90,6 +90,7 @@ public:
|
||||||
void setSize(const glm::vec2& size) { setSize(size.x, size.y); }
|
void setSize(const glm::vec2& size) { setSize(size.x, size.y); }
|
||||||
void setSize(const float w, const float h);
|
void setSize(const float w, const float h);
|
||||||
virtual void setResize(float width, float height) {}
|
virtual void setResize(float width, float height) {}
|
||||||
|
virtual void setResize(float width, float height, bool rasterize) {}
|
||||||
virtual void onSizeChanged() {}
|
virtual void onSizeChanged() {}
|
||||||
|
|
||||||
virtual glm::vec2 getRotationSize() const { return getSize(); }
|
virtual glm::vec2 getRotationSize() const { return getSize(); }
|
||||||
|
|
|
@ -36,6 +36,8 @@ ImageComponent::ImageComponent(bool forceLoad, bool dynamic)
|
||||||
, mFlipY {false}
|
, mFlipY {false}
|
||||||
, mTargetIsMax {false}
|
, mTargetIsMax {false}
|
||||||
, mTargetIsMin {false}
|
, mTargetIsMin {false}
|
||||||
|
, mTileWidth {0.0f}
|
||||||
|
, mTileHeight {0.0f}
|
||||||
, mColorShift {0xFFFFFFFF}
|
, mColorShift {0xFFFFFFFF}
|
||||||
, mColorShiftEnd {0xFFFFFFFF}
|
, mColorShiftEnd {0xFFFFFFFF}
|
||||||
, mColorGradientHorizontal {true}
|
, mColorGradientHorizontal {true}
|
||||||
|
@ -164,14 +166,15 @@ void ImageComponent::setImage(const std::string& path, bool tile)
|
||||||
// we perform the actual rasterization to have the cache entry updated with the proper
|
// we perform the actual rasterization to have the cache entry updated with the proper
|
||||||
// texture. For SVG images this requires that every call to setImage is made only after
|
// texture. For SVG images this requires that every call to setImage is made only after
|
||||||
// a call to setResize or setMaxSize (so the requested size is known upfront).
|
// a call to setResize or setMaxSize (so the requested size is known upfront).
|
||||||
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation);
|
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation,
|
||||||
|
false, 0, 0, mTileWidth, mTileHeight);
|
||||||
|
|
||||||
if (isScalable) {
|
if (isScalable) {
|
||||||
resize(false);
|
resize(false);
|
||||||
mTexture.reset();
|
mTexture.reset();
|
||||||
mTexture =
|
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation,
|
||||||
TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation, false,
|
false, static_cast<size_t>(mSize.x),
|
||||||
static_cast<size_t>(mSize.x), static_cast<size_t>(mSize.y));
|
static_cast<size_t>(mSize.y), mTileWidth, mTileHeight);
|
||||||
mTexture->rasterizeAt(mSize.x, mSize.y);
|
mTexture->rasterizeAt(mSize.x, mSize.y);
|
||||||
onSizeChanged();
|
onSizeChanged();
|
||||||
}
|
}
|
||||||
|
@ -206,6 +209,14 @@ void ImageComponent::setResize(float width, float height)
|
||||||
resize();
|
resize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageComponent::setResize(float width, float height, bool rasterize)
|
||||||
|
{
|
||||||
|
mTargetSize = glm::vec2 {width, height};
|
||||||
|
mTargetIsMax = false;
|
||||||
|
mTargetIsMin = false;
|
||||||
|
resize(rasterize);
|
||||||
|
}
|
||||||
|
|
||||||
void ImageComponent::setMaxSize(const float width, const float height)
|
void ImageComponent::setMaxSize(const float width, const float height)
|
||||||
{
|
{
|
||||||
mTargetSize = glm::vec2 {width, height};
|
mTargetSize = glm::vec2 {width, height};
|
||||||
|
|
|
@ -30,6 +30,7 @@ public:
|
||||||
// Use an already existing texture.
|
// Use an already existing texture.
|
||||||
void setImage(const std::shared_ptr<TextureResource>& texture, bool resizeTexture = true);
|
void setImage(const std::shared_ptr<TextureResource>& texture, bool resizeTexture = true);
|
||||||
|
|
||||||
|
void setDynamic(bool state) { mDynamic = state; }
|
||||||
void onSizeChanged() override { updateVertices(); }
|
void onSizeChanged() override { updateVertices(); }
|
||||||
|
|
||||||
// Resize the image to fit this size. If one axis is zero, scale that axis to maintain
|
// Resize the image to fit this size. If one axis is zero, scale that axis to maintain
|
||||||
|
@ -38,7 +39,11 @@ public:
|
||||||
// Can be set before or after an image is loaded.
|
// Can be set before or after an image is loaded.
|
||||||
// setMaxSize() and setResize() are mutually exclusive.
|
// setMaxSize() and setResize() are mutually exclusive.
|
||||||
void setResize(const float width, const float height) override;
|
void setResize(const float width, const float height) override;
|
||||||
void setResize(const glm::vec2& size) { setResize(size.x, size.y); }
|
void setResize(const glm::vec2& size, bool rasterize = true)
|
||||||
|
{
|
||||||
|
setResize(size.x, size.y, rasterize);
|
||||||
|
}
|
||||||
|
void setResize(const float width, const float height, bool rasterize) override;
|
||||||
|
|
||||||
// Resize the image to be as large as possible but fit within a box of this size.
|
// Resize the image to be as large as possible but fit within a box of this size.
|
||||||
// Can be set before or after an image is loaded.
|
// Can be set before or after an image is loaded.
|
||||||
|
@ -46,6 +51,12 @@ public:
|
||||||
void setMaxSize(const float width, const float height);
|
void setMaxSize(const float width, const float height);
|
||||||
void setMaxSize(const glm::vec2& size) { setMaxSize(size.x, size.y); }
|
void setMaxSize(const glm::vec2& size) { setMaxSize(size.x, size.y); }
|
||||||
|
|
||||||
|
void setTileSize(const float width, const float height)
|
||||||
|
{
|
||||||
|
mTileWidth = width;
|
||||||
|
mTileHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec2 getRotationSize() const override { return mRotateByTargetSize ? mTargetSize : mSize; }
|
glm::vec2 getRotationSize() const override { return mRotateByTargetSize ? mTargetSize : mSize; }
|
||||||
|
|
||||||
// Applied AFTER image positioning and sizing.
|
// Applied AFTER image positioning and sizing.
|
||||||
|
@ -108,6 +119,9 @@ private:
|
||||||
bool mTargetIsMax;
|
bool mTargetIsMax;
|
||||||
bool mTargetIsMin;
|
bool mTargetIsMin;
|
||||||
|
|
||||||
|
float mTileWidth;
|
||||||
|
float mTileHeight;
|
||||||
|
|
||||||
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
|
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
|
||||||
// Used internally whenever the resizing parameters or texture change. This function also
|
// Used internally whenever the resizing parameters or texture change. This function also
|
||||||
// initiates the SVG rasterization unless explicitly told not to.
|
// initiates the SVG rasterization unless explicitly told not to.
|
||||||
|
|
|
@ -19,15 +19,21 @@ RatingComponent::RatingComponent(bool colorizeChanges)
|
||||||
, mColorChangedValue {DEFAULT_COLORSHIFT}
|
, mColorChangedValue {DEFAULT_COLORSHIFT}
|
||||||
, mColorShift {DEFAULT_COLORSHIFT}
|
, mColorShift {DEFAULT_COLORSHIFT}
|
||||||
, mColorShiftEnd {DEFAULT_COLORSHIFT}
|
, mColorShiftEnd {DEFAULT_COLORSHIFT}
|
||||||
, mUnfilledColor {DEFAULT_COLORSHIFT}
|
|
||||||
, mColorizeChanges {colorizeChanges}
|
, mColorizeChanges {colorizeChanges}
|
||||||
{
|
{
|
||||||
mFilledTexture = TextureResource::get(":/graphics/star_filled.svg", true);
|
mSize = glm::vec2 {mRenderer->getScreenHeight() * 0.06f * NUM_RATING_STARS,
|
||||||
mUnfilledTexture = TextureResource::get(":/graphics/star_unfilled.svg", true);
|
mRenderer->getScreenHeight() * 0.06f};
|
||||||
|
|
||||||
|
mIconFilled.setResize(mSize, false);
|
||||||
|
mIconFilled.setTileSize(mSize.y, mSize.y);
|
||||||
|
|
||||||
|
mIconUnfilled.setResize(mSize, false);
|
||||||
|
mIconUnfilled.setTileSize(mSize.y, mSize.y);
|
||||||
|
|
||||||
|
mIconFilled.setImage(std::string(":/graphics/star_filled.svg"), true);
|
||||||
|
mIconUnfilled.setImage(std::string(":/graphics/star_unfilled.svg"), true);
|
||||||
|
|
||||||
mValue = 0.5f;
|
mValue = 0.5f;
|
||||||
mSize = glm::vec2 {64.0f * NUM_RATING_STARS, 64.0f};
|
|
||||||
updateVertices();
|
|
||||||
updateColors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RatingComponent::setValue(const std::string& value)
|
void RatingComponent::setValue(const std::string& value)
|
||||||
|
@ -44,9 +50,9 @@ void RatingComponent::setValue(const std::string& value)
|
||||||
// color shift accordingly.
|
// color shift accordingly.
|
||||||
if (mColorizeChanges) {
|
if (mColorizeChanges) {
|
||||||
if (static_cast<int>(mValue * 10.0f) == mOriginalValue)
|
if (static_cast<int>(mValue * 10.0f) == mOriginalValue)
|
||||||
setColorShift(mColorOriginalValue);
|
mIconFilled.setColorShift(mColorOriginalValue);
|
||||||
else
|
else
|
||||||
setColorShift(mColorChangedValue);
|
mIconFilled.setColorShift(mColorChangedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the special situation where there is a fractional rating in the gamelist.xml
|
// For the special situation where there is a fractional rating in the gamelist.xml
|
||||||
|
@ -55,7 +61,7 @@ void RatingComponent::setValue(const std::string& value)
|
||||||
// been manually edited.
|
// been manually edited.
|
||||||
if (mColorizeChanges && mValue != stof(value)) {
|
if (mColorizeChanges && mValue != stof(value)) {
|
||||||
mOriginalValue = ICONCOLOR_USERMARKED;
|
mOriginalValue = ICONCOLOR_USERMARKED;
|
||||||
setColorShift(0x449944FF);
|
mIconFilled.setColorShift(0x449944FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mValue > 1.0f)
|
if (mValue > 1.0f)
|
||||||
|
@ -63,8 +69,6 @@ void RatingComponent::setValue(const std::string& value)
|
||||||
else if (mValue < 0.0f)
|
else if (mValue < 0.0f)
|
||||||
mValue = 0.0f;
|
mValue = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVertices();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RatingComponent::getValue() const
|
std::string RatingComponent::getValue() const
|
||||||
|
@ -83,117 +87,55 @@ std::string RatingComponent::getRatingValue(const std::string& rating)
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RatingComponent::setOpacity(float opacity)
|
|
||||||
{
|
|
||||||
mOpacity = opacity;
|
|
||||||
mColorShift =
|
|
||||||
(mColorShift >> 8 << 8) | static_cast<unsigned char>(mOpacity * mThemeOpacity * 255.0f);
|
|
||||||
updateColors();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatingComponent::setDimming(float dimming)
|
void RatingComponent::setDimming(float dimming)
|
||||||
{
|
{
|
||||||
mDimming = dimming;
|
mDimming = dimming;
|
||||||
mVertices[0].dimming = mDimming;
|
mIconFilled.setDimming(dimming);
|
||||||
mVertices[4].dimming = mDimming;
|
mIconUnfilled.setDimming(dimming);
|
||||||
}
|
|
||||||
|
|
||||||
void RatingComponent::setColorShift(unsigned int color)
|
|
||||||
{
|
|
||||||
mColorShift = color;
|
|
||||||
mColorShiftEnd = color;
|
|
||||||
|
|
||||||
// Grab the opacity from the color shift because we may need
|
|
||||||
// to apply it if fading in textures.
|
|
||||||
mOpacity = static_cast<float>(color & 0xff) / 255.0f;
|
|
||||||
updateColors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RatingComponent::onSizeChanged()
|
void RatingComponent::onSizeChanged()
|
||||||
{
|
{
|
||||||
// Make sure the size is not unreasonably large (which may be caused by a mistake in
|
mSize = glm::round(mSize);
|
||||||
// the theme configuration).
|
|
||||||
mSize.x = glm::clamp(mSize.x, 0.0f, mRenderer->getScreenWidth() / 2.0f);
|
|
||||||
mSize.y = glm::clamp(mSize.y, 0.0f, mRenderer->getScreenHeight() / 2.0f);
|
|
||||||
|
|
||||||
if (mSize.y == 0.0f)
|
if (mSize.x == 0.0f)
|
||||||
mSize.y = mSize.x / NUM_RATING_STARS;
|
|
||||||
else if (mSize.x == 0.0f)
|
|
||||||
mSize.x = mSize.y * NUM_RATING_STARS;
|
mSize.x = mSize.y * NUM_RATING_STARS;
|
||||||
|
|
||||||
if (mSize.y > 0.0f) {
|
mIconFilled.getTexture()->setSize(mSize.y, mSize.y);
|
||||||
if (mFilledTexture)
|
mIconFilled.setResize(glm::vec2 {mSize.y * NUM_RATING_STARS, mSize.y}, true);
|
||||||
mFilledTexture->rasterizeAt(mSize.y, mSize.y);
|
|
||||||
if (mUnfilledTexture)
|
|
||||||
mUnfilledTexture->rasterizeAt(mSize.y, mSize.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateVertices();
|
mIconUnfilled.getTexture()->setSize(mSize.y, mSize.y);
|
||||||
}
|
mIconUnfilled.setResize(glm::vec2 {mSize.y * NUM_RATING_STARS, mSize.y}, true);
|
||||||
|
|
||||||
void RatingComponent::updateVertices()
|
|
||||||
{
|
|
||||||
const float numStars {NUM_RATING_STARS};
|
|
||||||
const float h {getSize().y}; // Ss the same as a single star's width.
|
|
||||||
const float w {getSize().y * mValue * numStars};
|
|
||||||
const float fw {getSize().y * numStars};
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
mVertices[0] = {{0.0f, 0.0f}, {0.0f, 1.0f}, mColorShift};
|
|
||||||
mVertices[1] = {{0.0f, h }, {0.0f, 0.0f}, mColorShift};
|
|
||||||
mVertices[2] = {{w, 0.0f}, {mValue * numStars, 1.0f}, mColorShift};
|
|
||||||
mVertices[3] = {{w, h }, {mValue * numStars, 0.0f}, mColorShift};
|
|
||||||
|
|
||||||
mVertices[4] = {{0.0f, 0.0f}, {0.0f, 1.0f}, mColorShift};
|
|
||||||
mVertices[5] = {{0.0f, h }, {0.0f, 0.0f}, mColorShift};
|
|
||||||
mVertices[6] = {{fw, 0.0f}, {numStars, 1.0f}, mColorShift};
|
|
||||||
mVertices[7] = {{fw, h }, {numStars, 0.0f}, mColorShift};
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatingComponent::updateColors()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 8; ++i)
|
|
||||||
mVertices[i].color = mColorShift;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RatingComponent::render(const glm::mat4& parentTrans)
|
void RatingComponent::render(const glm::mat4& parentTrans)
|
||||||
{
|
{
|
||||||
if (!isVisible() || mFilledTexture == nullptr || mUnfilledTexture == nullptr ||
|
if (!isVisible() || mThemeOpacity == 0.0f || mOpacity == 0.0f)
|
||||||
mThemeOpacity == 0.0f)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glm::mat4 trans {parentTrans * getTransform()};
|
glm::mat4 trans {parentTrans * getTransform()};
|
||||||
|
|
||||||
mRenderer->setMatrix(trans);
|
mRenderer->setMatrix(trans);
|
||||||
|
|
||||||
if (mOpacity > 0.0f) {
|
mIconUnfilled.setOpacity(mOpacity * mThemeOpacity);
|
||||||
if (Settings::getInstance()->getBool("DebugImage")) {
|
mIconUnfilled.render(trans);
|
||||||
mRenderer->drawRect(0.0f, 0.0f, mSize.y * NUM_RATING_STARS, mSize.y, 0xFF000033,
|
|
||||||
0xFF000033);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mUnfilledTexture->bind()) {
|
// No need to render the filled texture if the value is zero.
|
||||||
if (mUnfilledColor != mColorShift) {
|
if (mValue == 0.0f)
|
||||||
for (int i = 0; i < 8; ++i)
|
return;
|
||||||
mVertices[i].color =
|
|
||||||
(mUnfilledColor & 0xFFFFFF00) + (mVertices[i].color & 0x000000FF);
|
|
||||||
}
|
|
||||||
|
|
||||||
mRenderer->drawTriangleStrips(&mVertices[4], 4);
|
glm::ivec2 clipPos {static_cast<int>(std::round(trans[3].x)),
|
||||||
mRenderer->bindTexture(0);
|
static_cast<int>(std::round(trans[3].y))};
|
||||||
|
glm::vec3 dimScaled {};
|
||||||
|
dimScaled.x = std::fabs(trans[3].x + mIconUnfilled.getSize().x);
|
||||||
|
dimScaled.y = std::fabs(trans[3].y + mIconUnfilled.getSize().y);
|
||||||
|
|
||||||
if (mUnfilledColor != mColorShift)
|
glm::ivec2 clipDim {static_cast<int>(std::round(dimScaled.x - std::round(trans[3].x)) * mValue),
|
||||||
updateColors();
|
static_cast<int>(std::round(dimScaled.y - trans[3].y))};
|
||||||
}
|
|
||||||
|
|
||||||
if (mFilledTexture->bind()) {
|
mIconFilled.setOpacity(mOpacity * mThemeOpacity);
|
||||||
mRenderer->drawTriangleStrips(&mVertices[0], 4);
|
mRenderer->pushClipRect(clipPos, clipDim);
|
||||||
mRenderer->bindTexture(0);
|
mIconFilled.render(trans);
|
||||||
}
|
mRenderer->popClipRect();
|
||||||
}
|
|
||||||
|
|
||||||
renderChildren(trans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RatingComponent::input(InputConfig* config, Input input)
|
bool RatingComponent::input(InputConfig* config, Input input)
|
||||||
|
@ -207,11 +149,10 @@ bool RatingComponent::input(InputConfig* config, Input input)
|
||||||
// set the color shift accordingly.
|
// set the color shift accordingly.
|
||||||
if (mColorizeChanges) {
|
if (mColorizeChanges) {
|
||||||
if (static_cast<int>(mValue * 10.0f) == mOriginalValue)
|
if (static_cast<int>(mValue * 10.0f) == mOriginalValue)
|
||||||
setColorShift(mColorOriginalValue);
|
mIconFilled.setColorShift(mColorOriginalValue);
|
||||||
else
|
else
|
||||||
setColorShift(mColorChangedValue);
|
mIconFilled.setColorShift(mColorChangedValue);
|
||||||
}
|
}
|
||||||
updateVertices();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GuiComponent::input(config, input);
|
return GuiComponent::input(config, input);
|
||||||
|
@ -228,44 +169,65 @@ void RatingComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
if (!elem)
|
if (!elem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Make sure the size is not unreasonably large (which may be caused by a mistake in
|
GuiComponent::applyTheme(theme, view, element, properties ^ ThemeFlags::SIZE);
|
||||||
// the theme configuration).
|
|
||||||
mSize.x = glm::clamp(mSize.x, 0.0f, mRenderer->getScreenWidth() / 2.0f);
|
|
||||||
mSize.y = glm::clamp(mSize.y, 0.0f, mRenderer->getScreenHeight() / 2.0f);
|
|
||||||
|
|
||||||
if (mSize.y == 0.0f)
|
glm::vec2 scale {getParent() ?
|
||||||
mSize.y = mSize.x / NUM_RATING_STARS;
|
getParent()->getSize() :
|
||||||
else if (mSize.x == 0.0f)
|
glm::vec2(Renderer::getScreenWidth(), Renderer::getScreenHeight())};
|
||||||
mSize.x = mSize.y * NUM_RATING_STARS;
|
|
||||||
|
|
||||||
const size_t sizeY {static_cast<size_t>(mSize.y)};
|
if (elem->has("size")) {
|
||||||
|
glm::vec2 ratingSize {elem->get<glm::vec2>("size")};
|
||||||
bool imgChanged {false};
|
if (ratingSize == glm::vec2 {0.0f, 0.0f}) {
|
||||||
if (properties & PATH && elem->has("filledPath")) {
|
LOG(LogWarning) << "RatingComponent: Invalid theme configuration, property <size> "
|
||||||
mFilledTexture = TextureResource::get(elem->get<std::string>("filledPath"), true, false,
|
"for element \""
|
||||||
true, false, false, sizeY, sizeY);
|
<< element.substr(7) << "\" is set to zero";
|
||||||
imgChanged = true;
|
ratingSize.y = 0.01;
|
||||||
|
}
|
||||||
|
if (ratingSize.x > 0.0f)
|
||||||
|
ratingSize.x = glm::clamp(ratingSize.x, 0.01f, 1.0f);
|
||||||
|
if (ratingSize.y > 0.0f)
|
||||||
|
ratingSize.y = glm::clamp(ratingSize.y, 0.01f, 0.5f);
|
||||||
|
mSize = ratingSize * scale;
|
||||||
|
if (mSize.y == 0.0f)
|
||||||
|
mSize.y = mSize.x / NUM_RATING_STARS;
|
||||||
|
else
|
||||||
|
mSize.x = mSize.y * NUM_RATING_STARS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mIconFilled.setTileSize(mSize.y, mSize.y);
|
||||||
|
mIconFilled.setResize(glm::vec2 {mSize}, false);
|
||||||
|
|
||||||
|
if (properties & PATH && elem->has("filledPath")) {
|
||||||
|
mIconFilled.setDynamic(true);
|
||||||
|
mIconFilled.setImage(std::string(elem->get<std::string>("filledPath")), true);
|
||||||
|
mIconFilled.getTexture()->setSize(mSize.y, mSize.y);
|
||||||
|
if (!mIconFilled.getTexture()->getScalable())
|
||||||
|
mIconFilled.onSizeChanged();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mIconFilled.setImage(std::string(":/graphics/star_filled.svg"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
mIconUnfilled.setTileSize(mSize.y, mSize.y);
|
||||||
|
mIconUnfilled.setResize(glm::vec2 {mSize}, false);
|
||||||
|
|
||||||
if (properties & PATH && elem->has("unfilledPath")) {
|
if (properties & PATH && elem->has("unfilledPath")) {
|
||||||
mUnfilledTexture = TextureResource::get(elem->get<std::string>("unfilledPath"), true, false,
|
mIconUnfilled.setDynamic(true);
|
||||||
true, false, false, sizeY, sizeY);
|
mIconUnfilled.setImage(std::string(elem->get<std::string>("unfilledPath")), true);
|
||||||
imgChanged = true;
|
mIconUnfilled.getTexture()->setSize(mSize.y, mSize.y);
|
||||||
|
if (!mIconUnfilled.getTexture()->getScalable())
|
||||||
|
mIconUnfilled.onSizeChanged();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mIconUnfilled.setImage(std::string(":/graphics/star_unfilled.svg"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties & COLOR) {
|
if (properties & COLOR) {
|
||||||
if (elem->has("color"))
|
if (elem->has("color")) {
|
||||||
setColorShift(elem->get<unsigned int>("color"));
|
mIconFilled.setColorShift(elem->get<unsigned int>("color"));
|
||||||
|
mIconUnfilled.setColorShift(elem->get<unsigned int>("color"));
|
||||||
if (elem->has("unfilledColor"))
|
}
|
||||||
mUnfilledColor = elem->get<unsigned int>("unfilledColor");
|
|
||||||
else
|
|
||||||
mUnfilledColor = mColorShift;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiComponent::applyTheme(theme, view, element, properties);
|
|
||||||
|
|
||||||
if (imgChanged)
|
|
||||||
onSizeChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<HelpPrompt> RatingComponent::getHelpPrompts()
|
std::vector<HelpPrompt> RatingComponent::getHelpPrompts()
|
||||||
|
|
|
@ -11,11 +11,12 @@
|
||||||
#define ES_APP_COMPONENTS_RATING_COMPONENT_H
|
#define ES_APP_COMPONENTS_RATING_COMPONENT_H
|
||||||
|
|
||||||
#include "GuiComponent.h"
|
#include "GuiComponent.h"
|
||||||
|
#include "components/ImageComponent.h"
|
||||||
#include "renderers/Renderer.h"
|
#include "renderers/Renderer.h"
|
||||||
|
|
||||||
class TextureResource;
|
class TextureResource;
|
||||||
|
|
||||||
#define NUM_RATING_STARS 5
|
#define NUM_RATING_STARS 5.0f
|
||||||
|
|
||||||
class RatingComponent : public GuiComponent
|
class RatingComponent : public GuiComponent
|
||||||
{
|
{
|
||||||
|
@ -32,14 +33,8 @@ public:
|
||||||
void render(const glm::mat4& parentTrans) override;
|
void render(const glm::mat4& parentTrans) override;
|
||||||
|
|
||||||
void onSizeChanged() override;
|
void onSizeChanged() override;
|
||||||
|
|
||||||
void setOpacity(float opacity) override;
|
|
||||||
void setDimming(float dimming) override;
|
void setDimming(float dimming) override;
|
||||||
|
|
||||||
// Multiply all pixels in the image by this color when rendering.
|
|
||||||
void setColorShift(unsigned int color) override;
|
|
||||||
unsigned int getColorShift() const override { return mColorShift; }
|
|
||||||
|
|
||||||
void setOriginalColor(unsigned int color) override { mColorOriginalValue = color; }
|
void setOriginalColor(unsigned int color) override { mColorOriginalValue = color; }
|
||||||
void setChangedColor(unsigned int color) override { mColorChangedValue = color; }
|
void setChangedColor(unsigned int color) override { mColorChangedValue = color; }
|
||||||
|
|
||||||
|
@ -51,23 +46,17 @@ public:
|
||||||
std::vector<HelpPrompt> getHelpPrompts() override;
|
std::vector<HelpPrompt> getHelpPrompts() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateVertices();
|
|
||||||
void updateColors();
|
|
||||||
|
|
||||||
Renderer* mRenderer;
|
Renderer* mRenderer;
|
||||||
|
ImageComponent mIconFilled;
|
||||||
|
ImageComponent mIconUnfilled;
|
||||||
|
|
||||||
float mValue;
|
float mValue;
|
||||||
int mOriginalValue;
|
int mOriginalValue;
|
||||||
|
|
||||||
unsigned int mColorOriginalValue;
|
unsigned int mColorOriginalValue;
|
||||||
unsigned int mColorChangedValue;
|
unsigned int mColorChangedValue;
|
||||||
|
|
||||||
Renderer::Vertex mVertices[8];
|
|
||||||
|
|
||||||
unsigned int mColorShift;
|
unsigned int mColorShift;
|
||||||
unsigned int mColorShiftEnd;
|
unsigned int mColorShiftEnd;
|
||||||
unsigned int mUnfilledColor;
|
|
||||||
|
|
||||||
std::shared_ptr<TextureResource> mFilledTexture;
|
|
||||||
std::shared_ptr<TextureResource> mUnfilledTexture;
|
|
||||||
|
|
||||||
bool mColorizeChanges;
|
bool mColorizeChanges;
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,6 +30,8 @@ TextureData::TextureData(bool tile)
|
||||||
, mDataRGBA {}
|
, mDataRGBA {}
|
||||||
, mWidth {0}
|
, mWidth {0}
|
||||||
, mHeight {0}
|
, mHeight {0}
|
||||||
|
, mTileWidth {0.0f}
|
||||||
|
, mTileHeight {0.0f}
|
||||||
, mSourceWidth {0.0f}
|
, mSourceWidth {0.0f}
|
||||||
, mSourceHeight {0.0f}
|
, mSourceHeight {0.0f}
|
||||||
, mScalable {false}
|
, mScalable {false}
|
||||||
|
@ -72,8 +74,14 @@ bool TextureData::initSVGFromMemory(const std::string& fileData)
|
||||||
bool rasterize {true};
|
bool rasterize {true};
|
||||||
|
|
||||||
if (mTile) {
|
if (mTile) {
|
||||||
mSourceWidth = svgImage->width;
|
if (mTileWidth == 0.0f && mTileHeight == 0.0f) {
|
||||||
mSourceHeight = svgImage->height;
|
mSourceWidth = svgImage->width;
|
||||||
|
mSourceHeight = svgImage->height;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mSourceWidth = static_cast<float>(mTileWidth);
|
||||||
|
mSourceHeight = static_cast<float>(mTileHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no image size defined yet, then don't rasterize unless mForceRasterization has
|
// If there is no image size defined yet, then don't rasterize unless mForceRasterization has
|
||||||
|
|
|
@ -57,6 +57,11 @@ public:
|
||||||
float sourceWidth();
|
float sourceWidth();
|
||||||
float sourceHeight();
|
float sourceHeight();
|
||||||
void setSourceSize(float width, float height);
|
void setSourceSize(float width, float height);
|
||||||
|
void setTileSize(float tileWidth, float tileHeight)
|
||||||
|
{
|
||||||
|
mTileWidth = tileWidth;
|
||||||
|
mTileHeight = tileHeight;
|
||||||
|
}
|
||||||
glm::vec2 getSize() { return glm::vec2 {static_cast<int>(mWidth), static_cast<int>(mHeight)}; }
|
glm::vec2 getSize() { return glm::vec2 {static_cast<int>(mWidth), static_cast<int>(mHeight)}; }
|
||||||
|
|
||||||
// Whether to use linear filtering when magnifying the texture.
|
// Whether to use linear filtering when magnifying the texture.
|
||||||
|
@ -82,6 +87,8 @@ private:
|
||||||
std::vector<unsigned char> mDataRGBA;
|
std::vector<unsigned char> mDataRGBA;
|
||||||
std::atomic<int> mWidth;
|
std::atomic<int> mWidth;
|
||||||
std::atomic<int> mHeight;
|
std::atomic<int> mHeight;
|
||||||
|
std::atomic<float> mTileWidth;
|
||||||
|
std::atomic<float> mTileHeight;
|
||||||
std::atomic<float> mSourceWidth;
|
std::atomic<float> mSourceWidth;
|
||||||
std::atomic<float> mSourceHeight;
|
std::atomic<float> mSourceHeight;
|
||||||
std::atomic<bool> mScalable;
|
std::atomic<bool> mScalable;
|
||||||
|
|
|
@ -14,8 +14,14 @@
|
||||||
#define DEBUG_RASTER_CACHING false
|
#define DEBUG_RASTER_CACHING false
|
||||||
#define DEBUG_SVG_CACHING false
|
#define DEBUG_SVG_CACHING false
|
||||||
|
|
||||||
TextureResource::TextureResource(
|
TextureResource::TextureResource(const std::string& path,
|
||||||
const std::string& path, bool tile, bool dynamic, bool linearMagnify, bool forceRasterization)
|
float tileWidth,
|
||||||
|
float tileHeight,
|
||||||
|
bool tile,
|
||||||
|
bool dynamic,
|
||||||
|
bool linearMagnify,
|
||||||
|
bool scalable,
|
||||||
|
bool forceRasterization)
|
||||||
: mTextureData {nullptr}
|
: mTextureData {nullptr}
|
||||||
, mForceLoad {false}
|
, mForceLoad {false}
|
||||||
{
|
{
|
||||||
|
@ -27,16 +33,17 @@ TextureResource::TextureResource(
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
data = sTextureDataManager.add(this, tile);
|
data = sTextureDataManager.add(this, tile);
|
||||||
data->initFromPath(path);
|
data->initFromPath(path);
|
||||||
|
data->setTileSize(tileWidth, tileHeight);
|
||||||
data->setLinearMagnify(linearMagnify);
|
data->setLinearMagnify(linearMagnify);
|
||||||
data->setForceRasterization(forceRasterization);
|
data->setForceRasterization(forceRasterization);
|
||||||
// Force the texture manager to load it using a blocking load.
|
// Force the texture manager to load it using a blocking load.
|
||||||
sTextureDataManager.load(data, true);
|
sTextureDataManager.load(data, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
mTextureData = std::shared_ptr<TextureData>(new TextureData(tile));
|
mTextureData = std::shared_ptr<TextureData>(new TextureData(tile));
|
||||||
data = mTextureData;
|
data = mTextureData;
|
||||||
data->initFromPath(path);
|
data->initFromPath(path);
|
||||||
|
data->setTileSize(tileWidth, tileHeight);
|
||||||
data->setLinearMagnify(linearMagnify);
|
data->setLinearMagnify(linearMagnify);
|
||||||
data->setForceRasterization(forceRasterization);
|
data->setForceRasterization(forceRasterization);
|
||||||
// Load it so we can read the width/height.
|
// Load it so we can read the width/height.
|
||||||
|
@ -151,12 +158,14 @@ std::shared_ptr<TextureResource> TextureResource::get(const std::string& path,
|
||||||
bool linearMagnify,
|
bool linearMagnify,
|
||||||
bool forceRasterization,
|
bool forceRasterization,
|
||||||
size_t width,
|
size_t width,
|
||||||
size_t height)
|
size_t height,
|
||||||
|
float tileWidth,
|
||||||
|
float tileHeight)
|
||||||
{
|
{
|
||||||
const std::string canonicalPath {Utils::FileSystem::getCanonicalPath(path)};
|
const std::string canonicalPath {Utils::FileSystem::getCanonicalPath(path)};
|
||||||
if (canonicalPath.empty()) {
|
if (canonicalPath.empty()) {
|
||||||
std::shared_ptr<TextureResource> tex(
|
std::shared_ptr<TextureResource> tex(new TextureResource(
|
||||||
new TextureResource("", tile, false, linearMagnify, forceRasterization));
|
"", tileWidth, tileHeight, tile, false, linearMagnify, false, forceRasterization));
|
||||||
// Make sure we get properly deinitialized even though we do nothing on reinitialization.
|
// Make sure we get properly deinitialized even though we do nothing on reinitialization.
|
||||||
ResourceManager::getInstance().addReloadable(tex);
|
ResourceManager::getInstance().addReloadable(tex);
|
||||||
return tex;
|
return tex;
|
||||||
|
@ -202,7 +211,8 @@ std::shared_ptr<TextureResource> TextureResource::get(const std::string& path,
|
||||||
|
|
||||||
// Need to create it.
|
// Need to create it.
|
||||||
std::shared_ptr<TextureResource> tex {std::shared_ptr<TextureResource>(
|
std::shared_ptr<TextureResource> tex {std::shared_ptr<TextureResource>(
|
||||||
new TextureResource(std::get<0>(key), tile, dynamic, linearMagnify, forceRasterization))};
|
new TextureResource(std::get<0>(key), tileWidth, tileHeight, tile, dynamic, linearMagnify,
|
||||||
|
isScalable, forceRasterization))};
|
||||||
std::shared_ptr<TextureData> data {sTextureDataManager.get(tex.get())};
|
std::shared_ptr<TextureData> data {sTextureDataManager.get(tex.get())};
|
||||||
|
|
||||||
if (!isScalable || (isScalable && width != 0.0f && height != 0.0f)) {
|
if (!isScalable || (isScalable && width != 0.0f && height != 0.0f)) {
|
||||||
|
|
|
@ -33,7 +33,9 @@ public:
|
||||||
bool linearMagnify = false,
|
bool linearMagnify = false,
|
||||||
bool forceRasterization = false,
|
bool forceRasterization = false,
|
||||||
size_t width = 0,
|
size_t width = 0,
|
||||||
size_t height = 0);
|
size_t height = 0,
|
||||||
|
float tileWidth = 0.0f,
|
||||||
|
float tileHeight = 0.0f);
|
||||||
void initFromPixels(const unsigned char* dataRGBA, size_t width, size_t height);
|
void initFromPixels(const unsigned char* dataRGBA, size_t width, size_t height);
|
||||||
virtual void initFromMemory(const char* data, size_t length);
|
virtual void initFromMemory(const char* data, size_t length);
|
||||||
static void manualUnload(const std::string& path, bool tile);
|
static void manualUnload(const std::string& path, bool tile);
|
||||||
|
@ -63,6 +65,11 @@ public:
|
||||||
virtual ~TextureResource();
|
virtual ~TextureResource();
|
||||||
|
|
||||||
bool isTiled() const;
|
bool isTiled() const;
|
||||||
|
void setSize(float width, float height)
|
||||||
|
{
|
||||||
|
mSize.x = static_cast<int>(std::round(width));
|
||||||
|
mSize.y = static_cast<int>(std::round(height));
|
||||||
|
}
|
||||||
|
|
||||||
const glm::ivec2 getSize() const { return mSize; }
|
const glm::ivec2 getSize() const { return mSize; }
|
||||||
bool bind();
|
bool bind();
|
||||||
|
@ -74,9 +81,12 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TextureResource(const std::string& path,
|
TextureResource(const std::string& path,
|
||||||
|
float tileWidth,
|
||||||
|
float tileHeight,
|
||||||
bool tile,
|
bool tile,
|
||||||
bool dynamic,
|
bool dynamic,
|
||||||
bool linearMagnify,
|
bool linearMagnify,
|
||||||
|
bool scalable,
|
||||||
bool forceRasterization);
|
bool forceRasterization);
|
||||||
virtual void unload(ResourceManager& rm);
|
virtual void unload(ResourceManager& rm);
|
||||||
virtual void reload(ResourceManager& rm);
|
virtual void reload(ResourceManager& rm);
|
||||||
|
|
Loading…
Reference in a new issue