Refactored RatingComponent to improve rendering accuracy and performance.

This commit is contained in:
Leon Styhre 2022-08-28 20:11:20 +02:00
parent 077c6abf3e
commit 48a9571609
9 changed files with 175 additions and 163 deletions

View file

@ -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(); }

View file

@ -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};

View file

@ -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.

View file

@ -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()

View file

@ -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;
}; };

View file

@ -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

View file

@ -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;

View file

@ -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)) {

View file

@ -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);