mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15: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 float w, const float h);
|
||||
virtual void setResize(float width, float height) {}
|
||||
virtual void setResize(float width, float height, bool rasterize) {}
|
||||
virtual void onSizeChanged() {}
|
||||
|
||||
virtual glm::vec2 getRotationSize() const { return getSize(); }
|
||||
|
|
|
@ -36,6 +36,8 @@ ImageComponent::ImageComponent(bool forceLoad, bool dynamic)
|
|||
, mFlipY {false}
|
||||
, mTargetIsMax {false}
|
||||
, mTargetIsMin {false}
|
||||
, mTileWidth {0.0f}
|
||||
, mTileHeight {0.0f}
|
||||
, mColorShift {0xFFFFFFFF}
|
||||
, mColorShiftEnd {0xFFFFFFFF}
|
||||
, 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
|
||||
// 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).
|
||||
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation);
|
||||
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation,
|
||||
false, 0, 0, mTileWidth, mTileHeight);
|
||||
|
||||
if (isScalable) {
|
||||
resize(false);
|
||||
mTexture.reset();
|
||||
mTexture =
|
||||
TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation, false,
|
||||
static_cast<size_t>(mSize.x), static_cast<size_t>(mSize.y));
|
||||
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation,
|
||||
false, static_cast<size_t>(mSize.x),
|
||||
static_cast<size_t>(mSize.y), mTileWidth, mTileHeight);
|
||||
mTexture->rasterizeAt(mSize.x, mSize.y);
|
||||
onSizeChanged();
|
||||
}
|
||||
|
@ -206,6 +209,14 @@ void ImageComponent::setResize(float width, float height)
|
|||
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)
|
||||
{
|
||||
mTargetSize = glm::vec2 {width, height};
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
// Use an already existing texture.
|
||||
void setImage(const std::shared_ptr<TextureResource>& texture, bool resizeTexture = true);
|
||||
|
||||
void setDynamic(bool state) { mDynamic = state; }
|
||||
void onSizeChanged() override { updateVertices(); }
|
||||
|
||||
// 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.
|
||||
// setMaxSize() and setResize() are mutually exclusive.
|
||||
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.
|
||||
// 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 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; }
|
||||
|
||||
// Applied AFTER image positioning and sizing.
|
||||
|
@ -108,6 +119,9 @@ private:
|
|||
bool mTargetIsMax;
|
||||
bool mTargetIsMin;
|
||||
|
||||
float mTileWidth;
|
||||
float mTileHeight;
|
||||
|
||||
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
|
||||
// Used internally whenever the resizing parameters or texture change. This function also
|
||||
// initiates the SVG rasterization unless explicitly told not to.
|
||||
|
|
|
@ -19,15 +19,21 @@ RatingComponent::RatingComponent(bool colorizeChanges)
|
|||
, mColorChangedValue {DEFAULT_COLORSHIFT}
|
||||
, mColorShift {DEFAULT_COLORSHIFT}
|
||||
, mColorShiftEnd {DEFAULT_COLORSHIFT}
|
||||
, mUnfilledColor {DEFAULT_COLORSHIFT}
|
||||
, mColorizeChanges {colorizeChanges}
|
||||
{
|
||||
mFilledTexture = TextureResource::get(":/graphics/star_filled.svg", true);
|
||||
mUnfilledTexture = TextureResource::get(":/graphics/star_unfilled.svg", true);
|
||||
mSize = glm::vec2 {mRenderer->getScreenHeight() * 0.06f * NUM_RATING_STARS,
|
||||
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;
|
||||
mSize = glm::vec2 {64.0f * NUM_RATING_STARS, 64.0f};
|
||||
updateVertices();
|
||||
updateColors();
|
||||
}
|
||||
|
||||
void RatingComponent::setValue(const std::string& value)
|
||||
|
@ -44,9 +50,9 @@ void RatingComponent::setValue(const std::string& value)
|
|||
// color shift accordingly.
|
||||
if (mColorizeChanges) {
|
||||
if (static_cast<int>(mValue * 10.0f) == mOriginalValue)
|
||||
setColorShift(mColorOriginalValue);
|
||||
mIconFilled.setColorShift(mColorOriginalValue);
|
||||
else
|
||||
setColorShift(mColorChangedValue);
|
||||
mIconFilled.setColorShift(mColorChangedValue);
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (mColorizeChanges && mValue != stof(value)) {
|
||||
mOriginalValue = ICONCOLOR_USERMARKED;
|
||||
setColorShift(0x449944FF);
|
||||
mIconFilled.setColorShift(0x449944FF);
|
||||
}
|
||||
|
||||
if (mValue > 1.0f)
|
||||
|
@ -63,8 +69,6 @@ void RatingComponent::setValue(const std::string& value)
|
|||
else if (mValue < 0.0f)
|
||||
mValue = 0.0f;
|
||||
}
|
||||
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
std::string RatingComponent::getValue() const
|
||||
|
@ -83,117 +87,55 @@ std::string RatingComponent::getRatingValue(const std::string& rating)
|
|||
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)
|
||||
{
|
||||
mDimming = dimming;
|
||||
mVertices[0].dimming = mDimming;
|
||||
mVertices[4].dimming = mDimming;
|
||||
}
|
||||
|
||||
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();
|
||||
mIconFilled.setDimming(dimming);
|
||||
mIconUnfilled.setDimming(dimming);
|
||||
}
|
||||
|
||||
void RatingComponent::onSizeChanged()
|
||||
{
|
||||
// Make sure the size is not unreasonably large (which may be caused by a mistake in
|
||||
// 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);
|
||||
mSize = glm::round(mSize);
|
||||
|
||||
if (mSize.y == 0.0f)
|
||||
mSize.y = mSize.x / NUM_RATING_STARS;
|
||||
else if (mSize.x == 0.0f)
|
||||
if (mSize.x == 0.0f)
|
||||
mSize.x = mSize.y * NUM_RATING_STARS;
|
||||
|
||||
if (mSize.y > 0.0f) {
|
||||
if (mFilledTexture)
|
||||
mFilledTexture->rasterizeAt(mSize.y, mSize.y);
|
||||
if (mUnfilledTexture)
|
||||
mUnfilledTexture->rasterizeAt(mSize.y, mSize.y);
|
||||
}
|
||||
mIconFilled.getTexture()->setSize(mSize.y, mSize.y);
|
||||
mIconFilled.setResize(glm::vec2 {mSize.y * NUM_RATING_STARS, mSize.y}, true);
|
||||
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
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;
|
||||
mIconUnfilled.getTexture()->setSize(mSize.y, mSize.y);
|
||||
mIconUnfilled.setResize(glm::vec2 {mSize.y * NUM_RATING_STARS, mSize.y}, true);
|
||||
}
|
||||
|
||||
void RatingComponent::render(const glm::mat4& parentTrans)
|
||||
{
|
||||
if (!isVisible() || mFilledTexture == nullptr || mUnfilledTexture == nullptr ||
|
||||
mThemeOpacity == 0.0f)
|
||||
if (!isVisible() || mThemeOpacity == 0.0f || mOpacity == 0.0f)
|
||||
return;
|
||||
|
||||
glm::mat4 trans {parentTrans * getTransform()};
|
||||
|
||||
mRenderer->setMatrix(trans);
|
||||
|
||||
if (mOpacity > 0.0f) {
|
||||
if (Settings::getInstance()->getBool("DebugImage")) {
|
||||
mRenderer->drawRect(0.0f, 0.0f, mSize.y * NUM_RATING_STARS, mSize.y, 0xFF000033,
|
||||
0xFF000033);
|
||||
}
|
||||
mIconUnfilled.setOpacity(mOpacity * mThemeOpacity);
|
||||
mIconUnfilled.render(trans);
|
||||
|
||||
if (mUnfilledTexture->bind()) {
|
||||
if (mUnfilledColor != mColorShift) {
|
||||
for (int i = 0; i < 8; ++i)
|
||||
mVertices[i].color =
|
||||
(mUnfilledColor & 0xFFFFFF00) + (mVertices[i].color & 0x000000FF);
|
||||
}
|
||||
// No need to render the filled texture if the value is zero.
|
||||
if (mValue == 0.0f)
|
||||
return;
|
||||
|
||||
mRenderer->drawTriangleStrips(&mVertices[4], 4);
|
||||
mRenderer->bindTexture(0);
|
||||
glm::ivec2 clipPos {static_cast<int>(std::round(trans[3].x)),
|
||||
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)
|
||||
updateColors();
|
||||
}
|
||||
glm::ivec2 clipDim {static_cast<int>(std::round(dimScaled.x - std::round(trans[3].x)) * mValue),
|
||||
static_cast<int>(std::round(dimScaled.y - trans[3].y))};
|
||||
|
||||
if (mFilledTexture->bind()) {
|
||||
mRenderer->drawTriangleStrips(&mVertices[0], 4);
|
||||
mRenderer->bindTexture(0);
|
||||
}
|
||||
}
|
||||
|
||||
renderChildren(trans);
|
||||
mIconFilled.setOpacity(mOpacity * mThemeOpacity);
|
||||
mRenderer->pushClipRect(clipPos, clipDim);
|
||||
mIconFilled.render(trans);
|
||||
mRenderer->popClipRect();
|
||||
}
|
||||
|
||||
bool RatingComponent::input(InputConfig* config, Input input)
|
||||
|
@ -207,11 +149,10 @@ bool RatingComponent::input(InputConfig* config, Input input)
|
|||
// set the color shift accordingly.
|
||||
if (mColorizeChanges) {
|
||||
if (static_cast<int>(mValue * 10.0f) == mOriginalValue)
|
||||
setColorShift(mColorOriginalValue);
|
||||
mIconFilled.setColorShift(mColorOriginalValue);
|
||||
else
|
||||
setColorShift(mColorChangedValue);
|
||||
mIconFilled.setColorShift(mColorChangedValue);
|
||||
}
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
return GuiComponent::input(config, input);
|
||||
|
@ -228,44 +169,65 @@ void RatingComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
|||
if (!elem)
|
||||
return;
|
||||
|
||||
// Make sure the size is not unreasonably large (which may be caused by a mistake in
|
||||
// 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);
|
||||
GuiComponent::applyTheme(theme, view, element, properties ^ ThemeFlags::SIZE);
|
||||
|
||||
if (mSize.y == 0.0f)
|
||||
mSize.y = mSize.x / NUM_RATING_STARS;
|
||||
else if (mSize.x == 0.0f)
|
||||
mSize.x = mSize.y * NUM_RATING_STARS;
|
||||
glm::vec2 scale {getParent() ?
|
||||
getParent()->getSize() :
|
||||
glm::vec2(Renderer::getScreenWidth(), Renderer::getScreenHeight())};
|
||||
|
||||
const size_t sizeY {static_cast<size_t>(mSize.y)};
|
||||
|
||||
bool imgChanged {false};
|
||||
if (properties & PATH && elem->has("filledPath")) {
|
||||
mFilledTexture = TextureResource::get(elem->get<std::string>("filledPath"), true, false,
|
||||
true, false, false, sizeY, sizeY);
|
||||
imgChanged = true;
|
||||
if (elem->has("size")) {
|
||||
glm::vec2 ratingSize {elem->get<glm::vec2>("size")};
|
||||
if (ratingSize == glm::vec2 {0.0f, 0.0f}) {
|
||||
LOG(LogWarning) << "RatingComponent: Invalid theme configuration, property <size> "
|
||||
"for element \""
|
||||
<< element.substr(7) << "\" is set to zero";
|
||||
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")) {
|
||||
mUnfilledTexture = TextureResource::get(elem->get<std::string>("unfilledPath"), true, false,
|
||||
true, false, false, sizeY, sizeY);
|
||||
imgChanged = true;
|
||||
mIconUnfilled.setDynamic(true);
|
||||
mIconUnfilled.setImage(std::string(elem->get<std::string>("unfilledPath")), 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 (elem->has("color"))
|
||||
setColorShift(elem->get<unsigned int>("color"));
|
||||
|
||||
if (elem->has("unfilledColor"))
|
||||
mUnfilledColor = elem->get<unsigned int>("unfilledColor");
|
||||
else
|
||||
mUnfilledColor = mColorShift;
|
||||
if (elem->has("color")) {
|
||||
mIconFilled.setColorShift(elem->get<unsigned int>("color"));
|
||||
mIconUnfilled.setColorShift(elem->get<unsigned int>("color"));
|
||||
}
|
||||
}
|
||||
|
||||
GuiComponent::applyTheme(theme, view, element, properties);
|
||||
|
||||
if (imgChanged)
|
||||
onSizeChanged();
|
||||
}
|
||||
|
||||
std::vector<HelpPrompt> RatingComponent::getHelpPrompts()
|
||||
|
|
|
@ -11,11 +11,12 @@
|
|||
#define ES_APP_COMPONENTS_RATING_COMPONENT_H
|
||||
|
||||
#include "GuiComponent.h"
|
||||
#include "components/ImageComponent.h"
|
||||
#include "renderers/Renderer.h"
|
||||
|
||||
class TextureResource;
|
||||
|
||||
#define NUM_RATING_STARS 5
|
||||
#define NUM_RATING_STARS 5.0f
|
||||
|
||||
class RatingComponent : public GuiComponent
|
||||
{
|
||||
|
@ -32,14 +33,8 @@ public:
|
|||
void render(const glm::mat4& parentTrans) override;
|
||||
|
||||
void onSizeChanged() override;
|
||||
|
||||
void setOpacity(float opacity) 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 setChangedColor(unsigned int color) override { mColorChangedValue = color; }
|
||||
|
||||
|
@ -51,23 +46,17 @@ public:
|
|||
std::vector<HelpPrompt> getHelpPrompts() override;
|
||||
|
||||
private:
|
||||
void updateVertices();
|
||||
void updateColors();
|
||||
|
||||
Renderer* mRenderer;
|
||||
ImageComponent mIconFilled;
|
||||
ImageComponent mIconUnfilled;
|
||||
|
||||
float mValue;
|
||||
int mOriginalValue;
|
||||
|
||||
unsigned int mColorOriginalValue;
|
||||
unsigned int mColorChangedValue;
|
||||
|
||||
Renderer::Vertex mVertices[8];
|
||||
|
||||
unsigned int mColorShift;
|
||||
unsigned int mColorShiftEnd;
|
||||
unsigned int mUnfilledColor;
|
||||
|
||||
std::shared_ptr<TextureResource> mFilledTexture;
|
||||
std::shared_ptr<TextureResource> mUnfilledTexture;
|
||||
|
||||
bool mColorizeChanges;
|
||||
};
|
||||
|
|
|
@ -30,6 +30,8 @@ TextureData::TextureData(bool tile)
|
|||
, mDataRGBA {}
|
||||
, mWidth {0}
|
||||
, mHeight {0}
|
||||
, mTileWidth {0.0f}
|
||||
, mTileHeight {0.0f}
|
||||
, mSourceWidth {0.0f}
|
||||
, mSourceHeight {0.0f}
|
||||
, mScalable {false}
|
||||
|
@ -72,8 +74,14 @@ bool TextureData::initSVGFromMemory(const std::string& fileData)
|
|||
bool rasterize {true};
|
||||
|
||||
if (mTile) {
|
||||
mSourceWidth = svgImage->width;
|
||||
mSourceHeight = svgImage->height;
|
||||
if (mTileWidth == 0.0f && mTileHeight == 0.0f) {
|
||||
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
|
||||
|
|
|
@ -57,6 +57,11 @@ public:
|
|||
float sourceWidth();
|
||||
float sourceHeight();
|
||||
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)}; }
|
||||
|
||||
// Whether to use linear filtering when magnifying the texture.
|
||||
|
@ -82,6 +87,8 @@ private:
|
|||
std::vector<unsigned char> mDataRGBA;
|
||||
std::atomic<int> mWidth;
|
||||
std::atomic<int> mHeight;
|
||||
std::atomic<float> mTileWidth;
|
||||
std::atomic<float> mTileHeight;
|
||||
std::atomic<float> mSourceWidth;
|
||||
std::atomic<float> mSourceHeight;
|
||||
std::atomic<bool> mScalable;
|
||||
|
|
|
@ -14,8 +14,14 @@
|
|||
#define DEBUG_RASTER_CACHING false
|
||||
#define DEBUG_SVG_CACHING false
|
||||
|
||||
TextureResource::TextureResource(
|
||||
const std::string& path, bool tile, bool dynamic, bool linearMagnify, bool forceRasterization)
|
||||
TextureResource::TextureResource(const std::string& path,
|
||||
float tileWidth,
|
||||
float tileHeight,
|
||||
bool tile,
|
||||
bool dynamic,
|
||||
bool linearMagnify,
|
||||
bool scalable,
|
||||
bool forceRasterization)
|
||||
: mTextureData {nullptr}
|
||||
, mForceLoad {false}
|
||||
{
|
||||
|
@ -27,16 +33,17 @@ TextureResource::TextureResource(
|
|||
if (dynamic) {
|
||||
data = sTextureDataManager.add(this, tile);
|
||||
data->initFromPath(path);
|
||||
data->setTileSize(tileWidth, tileHeight);
|
||||
data->setLinearMagnify(linearMagnify);
|
||||
data->setForceRasterization(forceRasterization);
|
||||
// Force the texture manager to load it using a blocking load.
|
||||
sTextureDataManager.load(data, true);
|
||||
}
|
||||
else {
|
||||
|
||||
mTextureData = std::shared_ptr<TextureData>(new TextureData(tile));
|
||||
data = mTextureData;
|
||||
data->initFromPath(path);
|
||||
data->setTileSize(tileWidth, tileHeight);
|
||||
data->setLinearMagnify(linearMagnify);
|
||||
data->setForceRasterization(forceRasterization);
|
||||
// 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 forceRasterization,
|
||||
size_t width,
|
||||
size_t height)
|
||||
size_t height,
|
||||
float tileWidth,
|
||||
float tileHeight)
|
||||
{
|
||||
const std::string canonicalPath {Utils::FileSystem::getCanonicalPath(path)};
|
||||
if (canonicalPath.empty()) {
|
||||
std::shared_ptr<TextureResource> tex(
|
||||
new TextureResource("", tile, false, linearMagnify, forceRasterization));
|
||||
std::shared_ptr<TextureResource> tex(new TextureResource(
|
||||
"", tileWidth, tileHeight, tile, false, linearMagnify, false, forceRasterization));
|
||||
// Make sure we get properly deinitialized even though we do nothing on reinitialization.
|
||||
ResourceManager::getInstance().addReloadable(tex);
|
||||
return tex;
|
||||
|
@ -202,7 +211,8 @@ std::shared_ptr<TextureResource> TextureResource::get(const std::string& path,
|
|||
|
||||
// Need to create it.
|
||||
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())};
|
||||
|
||||
if (!isScalable || (isScalable && width != 0.0f && height != 0.0f)) {
|
||||
|
|
|
@ -33,7 +33,9 @@ public:
|
|||
bool linearMagnify = false,
|
||||
bool forceRasterization = false,
|
||||
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);
|
||||
virtual void initFromMemory(const char* data, size_t length);
|
||||
static void manualUnload(const std::string& path, bool tile);
|
||||
|
@ -63,6 +65,11 @@ public:
|
|||
virtual ~TextureResource();
|
||||
|
||||
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; }
|
||||
bool bind();
|
||||
|
@ -74,9 +81,12 @@ public:
|
|||
|
||||
protected:
|
||||
TextureResource(const std::string& path,
|
||||
float tileWidth,
|
||||
float tileHeight,
|
||||
bool tile,
|
||||
bool dynamic,
|
||||
bool linearMagnify,
|
||||
bool scalable,
|
||||
bool forceRasterization);
|
||||
virtual void unload(ResourceManager& rm);
|
||||
virtual void reload(ResourceManager& rm);
|
||||
|
|
Loading…
Reference in a new issue