Optimized the hell out of ImageComponent.

(been saving this one for a rainy day...)
Fixed sort order assert triggered by std::sort when sorting help prompts.
This commit is contained in:
Aloshi 2014-04-11 20:48:13 -05:00
parent 9955261a1e
commit ac0bdb47ed
3 changed files with 105 additions and 88 deletions

View file

@ -197,7 +197,7 @@ void Window::render()
mHelp->render(transform);
if(Settings::getInstance()->getBool("DrawFramerate"))
if(Settings::getInstance()->getBool("DrawFramerate") && mFrameDataText)
{
Renderer::setMatrix(Eigen::Affine3f::Identity());
mDefaultFonts.at(1)->renderTextCache(mFrameDataText.get());
@ -254,16 +254,18 @@ void Window::setHelpPrompts(const std::vector<HelpPrompt>& prompts)
};
int i = 0;
int aVal = 0;
int bVal = 0;
while(map[i] != NULL)
{
if(a.first == map[i])
return true;
else if(b.first == map[i])
return false;
aVal = i;
if(b.first == map[i])
bVal = i;
i++;
}
return true;
return aVal > bVal;
});
mHelp->setPrompts(addPrompts);

View file

@ -25,6 +25,7 @@ Eigen::Vector2f ImageComponent::getCenter() const
ImageComponent::ImageComponent(Window* window) : GuiComponent(window),
mTargetIsMax(false), mFlipX(false), mFlipY(false), mOrigin(0.0, 0.0), mTargetSize(0, 0), mColorShift(0xFFFFFFFF)
{
updateColors();
}
ImageComponent::~ImageComponent()
@ -80,6 +81,13 @@ void ImageComponent::resize()
{
svg->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
}
onSizeChanged();
}
void ImageComponent::onSizeChanged()
{
updateVertices();
}
void ImageComponent::setImage(std::string path, bool tile)
@ -111,6 +119,7 @@ void ImageComponent::setImage(const std::shared_ptr<TextureResource>& texture)
void ImageComponent::setOrigin(float originX, float originY)
{
mOrigin << originX, originY;
updateVertices();
}
void ImageComponent::setResize(float width, float height)
@ -130,54 +139,33 @@ void ImageComponent::setMaxSize(float width, float height)
void ImageComponent::setFlipX(bool flip)
{
mFlipX = flip;
updateVertices();
}
void ImageComponent::setFlipY(bool flip)
{
mFlipY = flip;
updateVertices();
}
void ImageComponent::setColorShift(unsigned int color)
{
mColorShift = color;
updateColors();
}
void ImageComponent::render(const Eigen::Affine3f& parentTrans)
void ImageComponent::setOpacity(unsigned char opacity)
{
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
Renderer::setMatrix(trans);
if(mTexture && getOpacity() > 0)
{
if(mTexture->isInitialized())
{
GLfloat points[12], texs[12];
GLubyte colors[6*4];
if(mTexture->isTiled())
{
float xCount = mSize.x() / getTextureSize().x();
float yCount = mSize.y() / getTextureSize().y();
Renderer::buildGLColorArray(colors, (mColorShift >> 8 << 8)| (getOpacity()), 6);
buildImageArray(points, texs, xCount, yCount);
}else{
Renderer::buildGLColorArray(colors, (mColorShift >> 8 << 8) | (getOpacity()), 6);
buildImageArray(points, texs);
}
drawImageArray(points, texs, colors, 6);
}else{
LOG(LogError) << "Image texture is not initialized!";
mTexture.reset();
}
}
GuiComponent::renderChildren(trans);
mOpacity = opacity;
mColorShift = (mColorShift >> 8 << 8) | mOpacity;
updateColors();
}
void ImageComponent::buildImageArray(GLfloat* points, GLfloat* texs, float px, float py)
void ImageComponent::updateVertices()
{
if(!mTexture || !mTexture->isInitialized())
return;
// we go through this mess to make sure everything is properly rounded
// if we just round vertices at the end, edge cases occur near sizes of 0.5
Eigen::Vector2f topLeft(-mSize.x() * mOrigin.x(), -mSize.y() * mOrigin.y());
@ -191,70 +179,88 @@ void ImageComponent::buildImageArray(GLfloat* points, GLfloat* texs, float px, f
bottomRight[0] = topLeft[0] + width;
bottomRight[1] = topLeft[1] + height;
points[0] = topLeft.x(); points[1] = topLeft.y();
points[2] = topLeft.x(); points[3] = bottomRight.y();
points[4] = bottomRight.x(); points[5] = topLeft.y();
mVertices[0].pos << topLeft.x(), topLeft.y();
mVertices[1].pos << topLeft.x(), bottomRight.y();
mVertices[2].pos << bottomRight.x(), topLeft.y();
points[6] = bottomRight.x(); points[7] = topLeft.y();
points[8] = topLeft.x(); points[9] = bottomRight.y();
points[10] = bottomRight.x(); points[11] = bottomRight.y();
mVertices[3].pos << bottomRight.x(), topLeft.y();
mVertices[4].pos << topLeft.x(), bottomRight.y();
mVertices[5].pos << bottomRight.x(), bottomRight.y();
texs[0] = 0; texs[1] = py;
texs[2] = 0; texs[3] = 0;
texs[4] = px; texs[5] = py;
float px, py;
if(mTexture->isTiled())
{
px = mSize.x() / getTextureSize().x();
py = mSize.y() / getTextureSize().y();
}else{
px = 1;
py = 1;
}
texs[6] = px; texs[7] = py;
texs[8] = 0; texs[9] = 0;
texs[10] = px; texs[11] = 0;
mVertices[0].tex << 0, py;
mVertices[1].tex << 0, 0;
mVertices[2].tex << px, py;
mVertices[3].tex << px, py;
mVertices[4].tex << 0, 0;
mVertices[5].tex << px, 0;
if(mFlipX)
{
for(int i = 0; i < 11; i += 2)
if(texs[i] == px)
texs[i] = 0;
else
texs[i] = px;
for(int i = 0; i < 6; i++)
mVertices[i].tex[0] = mVertices[i].tex[0] == px ? 0 : px;
}
if(mFlipY)
{
for(int i = 1; i < 12; i += 2)
if(texs[i] == py)
texs[i] = 0;
else
texs[i] = py;
for(int i = 1; i < 6; i++)
mVertices[i].tex[1] = mVertices[i].tex[1] == py ? 0 : py;
}
}
void ImageComponent::drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* colors, unsigned int numArrays)
void ImageComponent::updateColors()
{
mTexture->bind();
Renderer::buildGLColorArray(mColors, (mColorShift >> 8 << 8)| (getOpacity()), 6);
}
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);
if(colors != NULL)
void ImageComponent::render(const Eigen::Affine3f& parentTrans)
{
Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform());
Renderer::setMatrix(trans);
if(mTexture && mOpacity > 0)
{
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
if(mTexture->isInitialized())
{
// actually draw the image
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);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}else{
LOG(LogError) << "Image texture is not initialized!";
mTexture.reset();
}
}
glVertexPointer(2, GL_FLOAT, 0, points);
glTexCoordPointer(2, GL_FLOAT, 0, texs);
glDrawArrays(GL_TRIANGLES, 0, numArrays);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if(colors != NULL)
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
GuiComponent::renderChildren(trans);
}
bool ImageComponent::hasImage()

View file

@ -22,6 +22,9 @@ public:
//Use an already existing texture.
void setImage(const std::shared_ptr<TextureResource>& texture);
void onSizeChanged() override;
void setOpacity(unsigned char opacity) override;
//Sets the origin as a percentage of this image (e.g. (0, 0) is top left, (0.5, 0.5) is the center)
void setOrigin(float originX, float originY);
inline void setOrigin(Eigen::Vector2f origin) { setOrigin(origin.x(), origin.y()); }
@ -67,10 +70,16 @@ private:
// Used internally whenever the resizing parameters or texture change.
void resize();
// Writes 12 GLfloat points and 12 GLfloat texture coordinates to a given array at a given position.
void buildImageArray(GLfloat* points, GLfloat* texs, float percentageX = 1, float percentageY = 1);
// Draws the given set of points and texture coordinates, number of coordinate pairs may be specified.
void drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* colors, unsigned int count = 6);
struct Vertex
{
Eigen::Vector2f pos;
Eigen::Vector2f tex;
} mVertices[6];
GLubyte mColors[6*4];
void updateVertices();
void updateColors();
unsigned int mColorShift;