2014-06-20 01:30:09 +00:00
|
|
|
#include "components/NinePatchComponent.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
|
|
|
|
#include "resources/TextureResource.h"
|
2014-06-20 01:30:09 +00:00
|
|
|
#include "Log.h"
|
|
|
|
#include "Renderer.h"
|
|
|
|
#include "ThemeData.h"
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
NinePatchComponent::NinePatchComponent(Window* window, const std::string& path, unsigned int edgeColor, unsigned int centerColor) : GuiComponent(window),
|
|
|
|
mEdgeColor(edgeColor), mCenterColor(centerColor),
|
2013-09-14 15:58:34 +00:00
|
|
|
mPath(path),
|
2013-08-23 02:41:40 +00:00
|
|
|
mVertices(NULL), mColors(NULL)
|
|
|
|
{
|
2013-09-14 17:51:13 +00:00
|
|
|
if(!mPath.empty())
|
|
|
|
buildVertices();
|
2013-08-23 02:41:40 +00:00
|
|
|
}
|
|
|
|
|
2015-02-09 22:23:36 +00:00
|
|
|
NinePatchComponent::~NinePatchComponent()
|
|
|
|
{
|
|
|
|
if (mVertices != NULL)
|
|
|
|
delete[] mVertices;
|
|
|
|
|
|
|
|
if (mColors != NULL)
|
|
|
|
delete[] mColors;
|
|
|
|
}
|
|
|
|
|
2013-09-14 15:58:34 +00:00
|
|
|
void NinePatchComponent::updateColors()
|
|
|
|
{
|
|
|
|
Renderer::buildGLColorArray(mColors, mEdgeColor, 6 * 9);
|
|
|
|
Renderer::buildGLColorArray(&mColors[4 * 6 * 4], mCenterColor, 6);
|
|
|
|
}
|
|
|
|
|
2013-08-23 02:41:40 +00:00
|
|
|
void NinePatchComponent::buildVertices()
|
|
|
|
{
|
|
|
|
if(mVertices != NULL)
|
|
|
|
delete[] mVertices;
|
|
|
|
|
|
|
|
if(mColors != NULL)
|
|
|
|
delete[] mColors;
|
|
|
|
|
2013-10-04 23:09:54 +00:00
|
|
|
mTexture = TextureResource::get(mPath);
|
2013-09-14 15:58:34 +00:00
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
if(mTexture->getSize() == Vector2i::Zero())
|
2013-08-23 02:41:40 +00:00
|
|
|
{
|
|
|
|
mVertices = NULL;
|
|
|
|
mColors = NULL;
|
|
|
|
LOG(LogWarning) << "NinePatchComponent missing texture!";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mVertices = new Vertex[6 * 9];
|
|
|
|
mColors = new GLubyte[6 * 9 * 4];
|
2013-09-14 15:58:34 +00:00
|
|
|
updateColors();
|
2013-08-23 02:41:40 +00:00
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
const Vector2f ts = Vector2f(mTexture->getSize().x(), mTexture->getSize().y());
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
//coordinates on the image in pixels, top left origin
|
2017-10-28 20:24:35 +00:00
|
|
|
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),
|
2013-08-23 02:41:40 +00:00
|
|
|
};
|
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
const Vector2f pieceSizes = getCornerSize();
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
//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]
|
2014-03-25 23:41:50 +00:00
|
|
|
//if(borderWidth < pieceSizes.x())
|
|
|
|
// borderWidth = pieceSizes.x();
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
float borderHeight = mSize.y() - (pieceSizes.y() * 2); //should be pieceSizes[0] and pieceSizes[6]
|
2014-03-25 23:41:50 +00:00
|
|
|
//if(borderHeight < pieceSizes.y())
|
|
|
|
// borderHeight = pieceSizes.y();
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
mVertices[0 * 6].pos = pieceCoords[0]; //top left
|
|
|
|
mVertices[1 * 6].pos = pieceCoords[1]; //top middle
|
2017-10-28 20:24:35 +00:00
|
|
|
mVertices[2 * 6].pos = pieceCoords[1] + Vector2f(borderWidth, 0); //top right
|
2013-08-23 02:41:40 +00:00
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
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
|
2013-08-23 02:41:40 +00:00
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
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
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
int v = 0;
|
|
|
|
for(int slice = 0; slice < 9; slice++)
|
|
|
|
{
|
2017-10-28 20:24:35 +00:00
|
|
|
Vector2f size;
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
//corners
|
|
|
|
if(slice == 0 || slice == 2 || slice == 6 || slice == 8)
|
|
|
|
size = pieceSizes;
|
|
|
|
|
|
|
|
//vertical borders
|
|
|
|
if(slice == 1 || slice == 7)
|
2017-10-28 20:24:35 +00:00
|
|
|
size = Vector2f(borderWidth, pieceSizes.y());
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
//horizontal borders
|
|
|
|
if(slice == 3 || slice == 5)
|
2017-10-28 20:24:35 +00:00
|
|
|
size = Vector2f(pieceSizes.x(), borderHeight);
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
//center
|
|
|
|
if(slice == 4)
|
2017-10-28 20:24:35 +00:00
|
|
|
size = Vector2f(borderWidth, borderHeight);
|
2013-08-23 02:41:40 +00:00
|
|
|
|
|
|
|
//no resizing will be necessary
|
|
|
|
//mVertices[v + 0] is already correct
|
|
|
|
mVertices[v + 1].pos = mVertices[v + 0].pos + size;
|
2017-10-28 20:24:35 +00:00
|
|
|
mVertices[v + 2].pos = Vector2f(mVertices[v + 0].pos.x(), mVertices[v + 1].pos.y());
|
2013-08-23 02:41:40 +00:00
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
mVertices[v + 3].pos = Vector2f(mVertices[v + 1].pos.x(), mVertices[v + 0].pos.y());
|
2013-08-23 02:41:40 +00:00
|
|
|
mVertices[v + 4].pos = mVertices[v + 1].pos;
|
|
|
|
mVertices[v + 5].pos = mVertices[v + 0].pos;
|
|
|
|
|
|
|
|
//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
|
2017-10-28 20:24:35 +00:00
|
|
|
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());
|
2013-08-23 02:41:40 +00:00
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
mVertices[v + 3].tex = Vector2f(mVertices[v + 1].tex.x(), mVertices[v + 0].tex.y());
|
2013-08-23 02:41:40 +00:00
|
|
|
mVertices[v + 4].tex = mVertices[v + 1].tex;
|
|
|
|
mVertices[v + 5].tex = mVertices[v + 0].tex;
|
|
|
|
|
|
|
|
v += 6;
|
|
|
|
}
|
2014-03-19 20:03:23 +00:00
|
|
|
|
|
|
|
// round vertices
|
|
|
|
for(int i = 0; i < 6*9; i++)
|
|
|
|
{
|
2017-10-28 20:24:35 +00:00
|
|
|
mVertices[i].pos.round();
|
2014-03-19 20:03:23 +00:00
|
|
|
}
|
2013-08-23 02:41:40 +00:00
|
|
|
}
|
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
void NinePatchComponent::render(const Transform4x4f& parentTrans)
|
2013-08-23 02:41:40 +00:00
|
|
|
{
|
2017-10-28 20:24:35 +00:00
|
|
|
Transform4x4f trans = parentTrans * getTransform();
|
|
|
|
trans.round();
|
2014-03-19 20:03:23 +00:00
|
|
|
|
2013-09-14 17:32:21 +00:00
|
|
|
if(mTexture && mVertices != NULL)
|
2013-08-23 02:41:40 +00:00
|
|
|
{
|
|
|
|
Renderer::setMatrix(trans);
|
|
|
|
|
|
|
|
mTexture->bind();
|
|
|
|
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
|
|
|
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &mVertices[0].pos);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &mVertices[0].tex);
|
|
|
|
glColorPointer(4, GL_UNSIGNED_BYTE, 0, mColors);
|
|
|
|
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, 6 * 9);
|
|
|
|
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderChildren(trans);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NinePatchComponent::onSizeChanged()
|
|
|
|
{
|
|
|
|
buildVertices();
|
|
|
|
}
|
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
Vector2f NinePatchComponent::getCornerSize() const
|
2013-08-23 02:41:40 +00:00
|
|
|
{
|
2017-10-28 20:24:35 +00:00
|
|
|
return Vector2f(16, 16);
|
2013-08-23 02:41:40 +00:00
|
|
|
}
|
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
void NinePatchComponent::fitTo(Vector2f size, Vector3f position, Vector2f padding)
|
2013-08-23 02:41:40 +00:00
|
|
|
{
|
2013-09-14 16:14:21 +00:00
|
|
|
size += padding;
|
|
|
|
position[0] -= padding.x() / 2;
|
|
|
|
position[1] -= padding.y() / 2;
|
|
|
|
|
2017-10-28 20:24:35 +00:00
|
|
|
setSize(size + Vector2f(getCornerSize().x() * 2, getCornerSize().y() * 2));
|
2013-09-14 16:14:21 +00:00
|
|
|
setPosition(-getCornerSize().x() + position.x(), -getCornerSize().y() + position.y());
|
2013-08-23 02:41:40 +00:00
|
|
|
}
|
2013-09-14 15:58:34 +00:00
|
|
|
|
|
|
|
void NinePatchComponent::setImagePath(const std::string& path)
|
|
|
|
{
|
|
|
|
mPath = path;
|
|
|
|
buildVertices();
|
|
|
|
}
|
|
|
|
|
|
|
|
void NinePatchComponent::setEdgeColor(unsigned int edgeColor)
|
|
|
|
{
|
|
|
|
mEdgeColor = edgeColor;
|
|
|
|
updateColors();
|
|
|
|
}
|
|
|
|
|
|
|
|
void NinePatchComponent::setCenterColor(unsigned int centerColor)
|
|
|
|
{
|
|
|
|
mCenterColor = centerColor;
|
|
|
|
updateColors();
|
|
|
|
}
|
2014-01-01 05:39:22 +00:00
|
|
|
|
|
|
|
void NinePatchComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
|
|
|
{
|
|
|
|
GuiComponent::applyTheme(theme, view, element, properties);
|
|
|
|
|
|
|
|
using namespace ThemeFlags;
|
|
|
|
|
|
|
|
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "ninepatch");
|
|
|
|
if(!elem)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(properties & PATH && elem->has("path"))
|
|
|
|
setImagePath(elem->get<std::string>("path"));
|
|
|
|
}
|