Skip to content

Commit

Permalink
Rewrite NinePatchComponent to handle images of all sizes
Browse files Browse the repository at this point in the history
- Rewrite NinePatchComponent to handle images with a different size than 48x48 px
- It's now possible to change the border sizes using setCornerSize function
  • Loading branch information
benjdero committed Apr 29, 2018
1 parent 4a1e9d5 commit 918ecbe
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 72 deletions.
108 changes: 38 additions & 70 deletions es-core/src/components/NinePatchComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include "ThemeData.h"

NinePatchComponent::NinePatchComponent(Window* window, const std::string& path, unsigned int edgeColor, unsigned int centerColor) : GuiComponent(window),
mEdgeColor(edgeColor), mCenterColor(centerColor),
mCornerSize(16, 16),
mEdgeColor(edgeColor), mCenterColor(centerColor),
mPath(path),
mVertices(NULL), mColors(NULL)
{
Expand Down Expand Up @@ -51,83 +52,44 @@ void NinePatchComponent::buildVertices()
mColors = new GLubyte[6 * 9 * 4];
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
const Vector2f pieceCoords[9] = {
Vector2f(0, 0),
Vector2f(16, 0),
Vector2f(32, 0),
Vector2f(0, 16),
Vector2f(16, 16),
Vector2f(32, 16),
Vector2f(0, 32),
Vector2f(16, 32),
Vector2f(32, 32),
};
float imgSizeX[3] = {mCornerSize.x(), mSize.x() - mCornerSize.x() * 2, mCornerSize.x()};
float imgSizeY[3] = {mCornerSize.y(), mSize.y() - mCornerSize.y() * 2, mCornerSize.y()};
float imgPosX[3] = {0, imgSizeX[0], imgSizeX[0] + imgSizeX[1]};
float imgPosY[3] = {0, imgSizeY[0], imgSizeY[0] + imgSizeY[1]};

const Vector2f pieceSizes = getCornerSize();

//corners never stretch, so we calculate a width and height for slices 1, 3, 5, and 7
float borderWidth = mSize.x() - (pieceSizes.x() * 2); //should be pieceSizes[0] and pieceSizes[2]
//if(borderWidth < pieceSizes.x())
// 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
//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()};
float texSizeY[3] = {-mCornerSize.y() / texSize.y(), -(texSize.y() - mCornerSize.y() * 2) / texSize.y(), -mCornerSize.y() / texSize.y()};
float texPosX[3] = {0, texSizeX[0], texSizeX[0] + texSizeX[1]};
float texPosY[3] = {1, 1 + texSizeY[0], 1 + texSizeY[0] + texSizeY[1]};

int v = 0;
for(int slice = 0; slice < 9; slice++)
{
Vector2f size;

//corners
if(slice == 0 || slice == 2 || slice == 6 || slice == 8)
size = pieceSizes;

//vertical borders
if(slice == 1 || slice == 7)
size = Vector2f(borderWidth, pieceSizes.y());
int sliceX = slice % 3;
int sliceY = slice / 3;

//horizontal borders
if(slice == 3 || slice == 5)
size = Vector2f(pieceSizes.x(), borderHeight);
Vector2f imgPos = Vector2f(imgPosX[sliceX], imgPosY[sliceY]);
Vector2f imgSize = Vector2f(imgSizeX[sliceX], imgSizeY[sliceY]);

//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 + 0].pos = imgPos;
mVertices[v + 1].pos = imgPos + Vector2f(0, imgSize.y());
mVertices[v + 2].pos = imgPos + Vector2f(imgSize.x(), 0);
mVertices[v + 3].pos = mVertices[v + 2].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
//the y = (1 - y) is to deal with texture coordinates having a bottom left corner origin vs. verticies having a top left origin
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());
Vector2f texPos = Vector2f(texPosX[sliceX], texPosY[sliceY]);
Vector2f texSize = Vector2f(texSizeX[sliceX], texSizeY[sliceY]);

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 + 5].tex = mVertices[v + 0].tex;
mVertices[v + 5].tex = texPos + texSize;

v += 6;
}
Expand Down Expand Up @@ -180,9 +142,15 @@ void NinePatchComponent::onSizeChanged()
buildVertices();
}

Vector2f NinePatchComponent::getCornerSize() const
const Vector2f& NinePatchComponent::getCornerSize() const
{
return mCornerSize;
}

void NinePatchComponent::setCornerSize(int sizeX, int sizeY)
{
return Vector2f(16, 16);
mCornerSize = Vector2f(sizeX, sizeY);
buildVertices();
}

void NinePatchComponent::fitTo(Vector2f size, Vector3f position, Vector2f padding)
Expand All @@ -191,8 +159,8 @@ void NinePatchComponent::fitTo(Vector2f size, Vector3f position, Vector2f paddin
position[0] -= padding.x() / 2;
position[1] -= padding.y() / 2;

setSize(size + Vector2f(getCornerSize().x() * 2, getCornerSize().y() * 2));
setPosition(-getCornerSize().x() + position.x(), -getCornerSize().y() + position.y());
setSize(size + mCornerSize * 2);
setPosition(-mCornerSize.x() + position.x(), -mCornerSize.y() + position.y());
}

void NinePatchComponent::setImagePath(const std::string& path)
Expand Down
7 changes: 5 additions & 2 deletions es-core/src/components/NinePatchComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ class NinePatchComponent : public GuiComponent

virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;

private:
Vector2f getCornerSize() const;
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 updateColors();

Expand All @@ -53,6 +55,7 @@ class NinePatchComponent : public GuiComponent
GLubyte* mColors;

std::string mPath;
Vector2f mCornerSize;
unsigned int mEdgeColor;
unsigned int mCenterColor;
std::shared_ptr<TextureResource> mTexture;
Expand Down

0 comments on commit 918ecbe

Please sign in to comment.