Rewrite NinePatchComponent to handle images of all sizes

- Rewrite NinePatchComponent to handle images with a different size than 48x48 px
- It's now possible to change the border sizes using setCornerSize function
This commit is contained in:
Koerty 2018-04-21 15:23:10 +02:00
parent 4a1e9d5f11
commit 918ecbe493
2 changed files with 43 additions and 72 deletions

View file

@ -6,6 +6,7 @@
#include "ThemeData.h" #include "ThemeData.h"
NinePatchComponent::NinePatchComponent(Window* window, const std::string& path, unsigned int edgeColor, unsigned int centerColor) : GuiComponent(window), NinePatchComponent::NinePatchComponent(Window* window, const std::string& path, unsigned int edgeColor, unsigned int centerColor) : GuiComponent(window),
mCornerSize(16, 16),
mEdgeColor(edgeColor), mCenterColor(centerColor), mEdgeColor(edgeColor), mCenterColor(centerColor),
mPath(path), mPath(path),
mVertices(NULL), mColors(NULL) mVertices(NULL), mColors(NULL)
@ -51,83 +52,44 @@ void NinePatchComponent::buildVertices()
mColors = new GLubyte[6 * 9 * 4]; mColors = new GLubyte[6 * 9 * 4];
updateColors(); updateColors();
const Vector2f ts = Vector2f((float)mTexture->getSize().x(), (float)mTexture->getSize().y()); const Vector2f texSize = Vector2f((float)mTexture->getSize().x(), (float)mTexture->getSize().y());
//coordinates on the image in pixels, top left origin float imgSizeX[3] = {mCornerSize.x(), mSize.x() - mCornerSize.x() * 2, mCornerSize.x()};
const Vector2f pieceCoords[9] = { float imgSizeY[3] = {mCornerSize.y(), mSize.y() - mCornerSize.y() * 2, mCornerSize.y()};
Vector2f(0, 0), float imgPosX[3] = {0, imgSizeX[0], imgSizeX[0] + imgSizeX[1]};
Vector2f(16, 0), float imgPosY[3] = {0, imgSizeY[0], imgSizeY[0] + imgSizeY[1]};
Vector2f(32, 0),
Vector2f(0, 16),
Vector2f(16, 16),
Vector2f(32, 16),
Vector2f(0, 32),
Vector2f(16, 32),
Vector2f(32, 32),
};
const Vector2f pieceSizes = getCornerSize(); //the "1 +" in posY and "-" in sizeY is to deal with texture coordinates having a bottom left corner origin vs. verticies having a top left origin
float texSizeX[3] = {mCornerSize.x() / texSize.x(), (texSize.x() - mCornerSize.x() * 2) / texSize.x(), mCornerSize.x() / texSize.x()};
//corners never stretch, so we calculate a width and height for slices 1, 3, 5, and 7 float texSizeY[3] = {-mCornerSize.y() / texSize.y(), -(texSize.y() - mCornerSize.y() * 2) / texSize.y(), -mCornerSize.y() / texSize.y()};
float borderWidth = mSize.x() - (pieceSizes.x() * 2); //should be pieceSizes[0] and pieceSizes[2] float texPosX[3] = {0, texSizeX[0], texSizeX[0] + texSizeX[1]};
//if(borderWidth < pieceSizes.x()) float texPosY[3] = {1, 1 + texSizeY[0], 1 + texSizeY[0] + texSizeY[1]};
// borderWidth = pieceSizes.x();
float borderHeight = mSize.y() - (pieceSizes.y() * 2); //should be pieceSizes[0] and pieceSizes[6]
//if(borderHeight < pieceSizes.y())
// borderHeight = pieceSizes.y();
mVertices[0 * 6].pos = pieceCoords[0]; //top left
mVertices[1 * 6].pos = pieceCoords[1]; //top middle
mVertices[2 * 6].pos = pieceCoords[1] + Vector2f(borderWidth, 0); //top right
mVertices[3 * 6].pos = mVertices[0 * 6].pos + Vector2f(0, pieceSizes.y()); //mid left
mVertices[4 * 6].pos = mVertices[3 * 6].pos + Vector2f(pieceSizes.x(), 0); //mid middle
mVertices[5 * 6].pos = mVertices[4 * 6].pos + Vector2f(borderWidth, 0); //mid right
mVertices[6 * 6].pos = mVertices[3 * 6].pos + Vector2f(0, borderHeight); //bot left
mVertices[7 * 6].pos = mVertices[6 * 6].pos + Vector2f(pieceSizes.x(), 0); //bot middle
mVertices[8 * 6].pos = mVertices[7 * 6].pos + Vector2f(borderWidth, 0); //bot right
int v = 0; int v = 0;
for(int slice = 0; slice < 9; slice++) for(int slice = 0; slice < 9; slice++)
{ {
Vector2f size; int sliceX = slice % 3;
int sliceY = slice / 3;
//corners Vector2f imgPos = Vector2f(imgPosX[sliceX], imgPosY[sliceY]);
if(slice == 0 || slice == 2 || slice == 6 || slice == 8) Vector2f imgSize = Vector2f(imgSizeX[sliceX], imgSizeY[sliceY]);
size = pieceSizes;
//vertical borders mVertices[v + 0].pos = imgPos;
if(slice == 1 || slice == 7) mVertices[v + 1].pos = imgPos + Vector2f(0, imgSize.y());
size = Vector2f(borderWidth, pieceSizes.y()); mVertices[v + 2].pos = imgPos + Vector2f(imgSize.x(), 0);
mVertices[v + 3].pos = mVertices[v + 2].pos;
//horizontal borders
if(slice == 3 || slice == 5)
size = Vector2f(pieceSizes.x(), borderHeight);
//center
if(slice == 4)
size = Vector2f(borderWidth, borderHeight);
//no resizing will be necessary
//mVertices[v + 0] is already correct
mVertices[v + 1].pos = mVertices[v + 0].pos + size;
mVertices[v + 2].pos = Vector2f(mVertices[v + 0].pos.x(), mVertices[v + 1].pos.y());
mVertices[v + 3].pos = Vector2f(mVertices[v + 1].pos.x(), mVertices[v + 0].pos.y());
mVertices[v + 4].pos = mVertices[v + 1].pos; mVertices[v + 4].pos = mVertices[v + 1].pos;
mVertices[v + 5].pos = mVertices[v + 0].pos; mVertices[v + 5].pos = imgPos + imgSize;
//texture coordinates Vector2f texPos = Vector2f(texPosX[sliceX], texPosY[sliceY]);
//the y = (1 - y) is to deal with texture coordinates having a bottom left corner origin vs. verticies having a top left origin Vector2f texSize = Vector2f(texSizeX[sliceX], texSizeY[sliceY]);
mVertices[v + 0].tex = Vector2f(pieceCoords[slice].x() / ts.x(), 1 - (pieceCoords[slice].y() / ts.y()));
mVertices[v + 1].tex = Vector2f((pieceCoords[slice].x() + pieceSizes.x()) / ts.x(), 1 - ((pieceCoords[slice].y() + pieceSizes.y()) / ts.y()));
mVertices[v + 2].tex = Vector2f(mVertices[v + 0].tex.x(), mVertices[v + 1].tex.y());
mVertices[v + 3].tex = Vector2f(mVertices[v + 1].tex.x(), mVertices[v + 0].tex.y()); mVertices[v + 0].tex = texPos;
mVertices[v + 1].tex = texPos + Vector2f(0, texSize.y());
mVertices[v + 2].tex = texPos + Vector2f(texSize.x(), 0);
mVertices[v + 3].tex = mVertices[v + 2].tex;
mVertices[v + 4].tex = mVertices[v + 1].tex; mVertices[v + 4].tex = mVertices[v + 1].tex;
mVertices[v + 5].tex = mVertices[v + 0].tex; mVertices[v + 5].tex = texPos + texSize;
v += 6; v += 6;
} }
@ -180,9 +142,15 @@ void NinePatchComponent::onSizeChanged()
buildVertices(); buildVertices();
} }
Vector2f NinePatchComponent::getCornerSize() const const Vector2f& NinePatchComponent::getCornerSize() const
{ {
return Vector2f(16, 16); return mCornerSize;
}
void NinePatchComponent::setCornerSize(int sizeX, int sizeY)
{
mCornerSize = Vector2f(sizeX, sizeY);
buildVertices();
} }
void NinePatchComponent::fitTo(Vector2f size, Vector3f position, Vector2f padding) void NinePatchComponent::fitTo(Vector2f size, Vector3f position, Vector2f padding)
@ -191,8 +159,8 @@ void NinePatchComponent::fitTo(Vector2f size, Vector3f position, Vector2f paddin
position[0] -= padding.x() / 2; position[0] -= padding.x() / 2;
position[1] -= padding.y() / 2; position[1] -= padding.y() / 2;
setSize(size + Vector2f(getCornerSize().x() * 2, getCornerSize().y() * 2)); setSize(size + mCornerSize * 2);
setPosition(-getCornerSize().x() + position.x(), -getCornerSize().y() + position.y()); setPosition(-mCornerSize.x() + position.x(), -mCornerSize.y() + position.y());
} }
void NinePatchComponent::setImagePath(const std::string& path) void NinePatchComponent::setImagePath(const std::string& path)

View file

@ -37,9 +37,11 @@ public:
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override; virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
private: const Vector2f& getCornerSize() const;
Vector2f getCornerSize() const; void setCornerSize(int sizeX, int sizeY);
inline void setCornerSize(const Vector2f& size) { setCornerSize(size.x(), size.y()); }
private:
void buildVertices(); void buildVertices();
void updateColors(); void updateColors();
@ -53,6 +55,7 @@ private:
GLubyte* mColors; GLubyte* mColors;
std::string mPath; std::string mPath;
Vector2f mCornerSize;
unsigned int mEdgeColor; unsigned int mEdgeColor;
unsigned int mCenterColor; unsigned int mCenterColor;
std::shared_ptr<TextureResource> mTexture; std::shared_ptr<TextureResource> mTexture;