performance improvments
This commit is contained in:
parent
da6dfea03e
commit
9b02312bf8
|
@ -30,6 +30,7 @@
|
||||||
#include "dispatcher.h"
|
#include "dispatcher.h"
|
||||||
#include "net/connections.h"
|
#include "net/connections.h"
|
||||||
#include "ui/uicontainer.h"
|
#include "ui/uicontainer.h"
|
||||||
|
#include "graphics/fonts.h"
|
||||||
|
|
||||||
Engine g_engine;
|
Engine g_engine;
|
||||||
|
|
||||||
|
@ -52,7 +53,10 @@ void Engine::terminate()
|
||||||
|
|
||||||
void Engine::run()
|
void Engine::run()
|
||||||
{
|
{
|
||||||
|
std::string fpsText;
|
||||||
|
Size fpsTextSize;
|
||||||
Font *defaultFont = g_fonts.getDefaultFont();
|
Font *defaultFont = g_fonts.getDefaultFont();
|
||||||
|
|
||||||
m_lastFrameTicks = Platform::getTicks();
|
m_lastFrameTicks = Platform::getTicks();
|
||||||
int lastFpsTicks = m_lastFrameTicks;
|
int lastFpsTicks = m_lastFrameTicks;
|
||||||
int frameCount = 0;
|
int frameCount = 0;
|
||||||
|
@ -60,14 +64,14 @@ void Engine::run()
|
||||||
m_running = true;
|
m_running = true;
|
||||||
|
|
||||||
while(!m_stopping) {
|
while(!m_stopping) {
|
||||||
|
m_lastFrameTicks = Platform::getTicks();
|
||||||
|
|
||||||
// poll platform events
|
// poll platform events
|
||||||
Platform::poll();
|
Platform::poll();
|
||||||
|
|
||||||
// poll network events
|
// poll network events
|
||||||
g_connections.poll();
|
g_connections.poll();
|
||||||
|
|
||||||
m_lastFrameTicks = Platform::getTicks();
|
|
||||||
|
|
||||||
// poll diaptcher tasks
|
// poll diaptcher tasks
|
||||||
g_dispatcher.poll();
|
g_dispatcher.poll();
|
||||||
|
|
||||||
|
@ -80,17 +84,18 @@ void Engine::run()
|
||||||
lastFpsTicks = m_lastFrameTicks;
|
lastFpsTicks = m_lastFrameTicks;
|
||||||
fps = frameCount;
|
fps = frameCount;
|
||||||
frameCount = 0;
|
frameCount = 0;
|
||||||
|
|
||||||
|
// update fps text
|
||||||
|
fpsText = format("FPS: %d", fps);
|
||||||
|
fpsTextSize = defaultFont->calculateTextRectSize(fpsText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render();
|
render();
|
||||||
|
|
||||||
// render fps
|
// render fps
|
||||||
if(m_calculateFps) {
|
if(m_calculateFps)
|
||||||
std::string fpsText = format("FPS: %d", fps);
|
defaultFont->renderText(fpsText, Point(g_graphics.getScreenSize().width() - fpsTextSize.width() - 10, 10));
|
||||||
Size textSize = defaultFont->calculateTextRectSize(fpsText);
|
|
||||||
defaultFont->renderText(fpsText, Point(g_graphics.getScreenSize().width() - textSize.width() - 10, 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
// swap buffers
|
// swap buffers
|
||||||
Platform::swapBuffers();
|
Platform::swapBuffers();
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "core/resources.h"
|
#include "core/resources.h"
|
||||||
#include "textures.h"
|
#include "textures.h"
|
||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
#include "textarea.h"
|
|
||||||
|
|
||||||
void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
|
void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +135,7 @@ void Font::renderText(const std::string& text,
|
||||||
{
|
{
|
||||||
Size boxSize = g_graphics.getScreenSize() - startPos.toSize();
|
Size boxSize = g_graphics.getScreenSize() - startPos.toSize();
|
||||||
Rect screenCoords(startPos, boxSize);
|
Rect screenCoords(startPos, boxSize);
|
||||||
Font::renderText(text, screenCoords, ALIGN_TOP_LEFT, color);
|
renderText(text, screenCoords, ALIGN_TOP_LEFT, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,34 +144,100 @@ void Font::renderText(const std::string& text,
|
||||||
int align,
|
int align,
|
||||||
const Color& color)
|
const Color& color)
|
||||||
{
|
{
|
||||||
TextArea textArea(this, text, screenCoords, align, color);
|
// prevent glitches from invalid rects
|
||||||
textArea.draw();
|
if(!screenCoords.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int textLenght = text.length();
|
||||||
|
|
||||||
|
// map glyphs positions
|
||||||
|
Size textBoxSize;
|
||||||
|
const std::vector<Point>& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize);
|
||||||
|
|
||||||
|
for(int i = 0; i < textLenght; ++i) {
|
||||||
|
int glyph = (uchar)text[i];
|
||||||
|
|
||||||
|
// skip invalid glyphs
|
||||||
|
if(glyph < 32)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// calculate initial glyph rect and texture coords
|
||||||
|
Rect glyphScreenCoords(glyphsPositions[i], m_glyphsSize[glyph]);
|
||||||
|
Rect glyphTextureCoords = m_glyphsTextureCoords[glyph];
|
||||||
|
|
||||||
|
// first translate to align position
|
||||||
|
if(align & ALIGN_BOTTOM) {
|
||||||
|
glyphScreenCoords.translate(0, screenCoords.height() - textBoxSize.height());
|
||||||
|
} else if(align & ALIGN_VERTICAL_CENTER) {
|
||||||
|
glyphScreenCoords.translate(0, (screenCoords.height() - textBoxSize.height()) / 2);
|
||||||
|
} else { // ALIGN_TOP
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
if(align & ALIGN_RIGHT) {
|
||||||
|
glyphScreenCoords.translate(screenCoords.width() - textBoxSize.width(), 0);
|
||||||
|
} else if(align & ALIGN_HORIZONTAL_CENTER) {
|
||||||
|
glyphScreenCoords.translate((screenCoords.width() - textBoxSize.width()) / 2, 0);
|
||||||
|
} else { // ALIGN_TOP
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate rect to screen coords
|
||||||
|
glyphScreenCoords.translate(screenCoords.topLeft());
|
||||||
|
|
||||||
|
// only render if glyph rect is visible on screenCoords
|
||||||
|
if(!screenCoords.intersects(glyphScreenCoords))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// bound glyph bottomRight to screenCoords bottomRight
|
||||||
|
if(glyphScreenCoords.bottom() > screenCoords.bottom()) {
|
||||||
|
glyphTextureCoords.setBottom(glyphTextureCoords.bottom() + (screenCoords.bottom() - glyphScreenCoords.bottom()));
|
||||||
|
glyphScreenCoords.setBottom(screenCoords.bottom());
|
||||||
|
}
|
||||||
|
if(glyphScreenCoords.right() > screenCoords.right()) {
|
||||||
|
glyphTextureCoords.setRight(glyphTextureCoords.right() + (screenCoords.right() - glyphScreenCoords.right()));
|
||||||
|
glyphScreenCoords.setRight(screenCoords.right());
|
||||||
|
}
|
||||||
|
|
||||||
|
// render glyph
|
||||||
|
g_graphics.drawTexturedRect(glyphScreenCoords, m_texture, glyphTextureCoords, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Point> Font::calculateGlyphsPositions(const std::string& text, int align, Size *textBoxSize)
|
const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text, int align, Size *textBoxSize) const
|
||||||
{
|
{
|
||||||
int numGlyphs = text.length();
|
// for performance reasons we use statics vectors that are allocated on demand
|
||||||
std::vector<Point> glyphsPositions(numGlyphs);
|
static std::vector<Point> glyphsPositions(1);
|
||||||
if(numGlyphs == 0) {
|
static std::vector<int> lineWidths(1);
|
||||||
if(textBoxSize)
|
|
||||||
textBoxSize->setSize(0,0);
|
|
||||||
return glyphsPositions;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<int> lineWidths(numGlyphs);
|
int textLength = text.length();
|
||||||
int maxLineWidth = 0;
|
int maxLineWidth = 0;
|
||||||
int lines = 0;
|
int lines = 0;
|
||||||
int glyph;
|
int glyph;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
// return if there is no text
|
||||||
|
if(textLength == 0) {
|
||||||
|
if(textBoxSize)
|
||||||
|
textBoxSize->setSize(0,0);
|
||||||
|
return glyphsPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize glyphsPositions vector, if needed
|
||||||
|
if(textLength > (int)glyphsPositions.size())
|
||||||
|
glyphsPositions.resize(textLength);
|
||||||
|
|
||||||
// calculate lines width
|
// calculate lines width
|
||||||
if((align & ALIGN_RIGHT || align & ALIGN_HORIZONTAL_CENTER) || textBoxSize) {
|
if((align & ALIGN_RIGHT || align & ALIGN_HORIZONTAL_CENTER) || textBoxSize) {
|
||||||
lineWidths[0] = 0;
|
lineWidths[0] = 0;
|
||||||
for(i = 0; i< numGlyphs; ++i) {
|
for(i = 0; i< textLength; ++i) {
|
||||||
glyph = (uchar)text[i];
|
glyph = (uchar)text[i];
|
||||||
|
|
||||||
if(glyph == (uchar)'\n') {
|
if(glyph == (uchar)'\n') {
|
||||||
lineWidths[++lines] = 0;
|
lines++;
|
||||||
|
if(lines+1 > (int)lineWidths.size())
|
||||||
|
lineWidths.resize(lines+1);
|
||||||
|
lineWidths[lines] = 0;
|
||||||
} else if(glyph >= 32) {
|
} else if(glyph >= 32) {
|
||||||
lineWidths[lines] += m_glyphsSize[glyph].width() + m_glyphSpacing.width();
|
lineWidths[lines] += m_glyphsSize[glyph].width() + m_glyphSpacing.width();
|
||||||
maxLineWidth = std::max(maxLineWidth, lineWidths[lines]);
|
maxLineWidth = std::max(maxLineWidth, lineWidths[lines]);
|
||||||
|
@ -182,7 +247,7 @@ std::vector<Point> Font::calculateGlyphsPositions(const std::string& text, int a
|
||||||
|
|
||||||
Point virtualPos(0, m_topMargin);
|
Point virtualPos(0, m_topMargin);
|
||||||
lines = 0;
|
lines = 0;
|
||||||
for(i = 0; i < numGlyphs; ++i) {
|
for(i = 0; i < textLength; ++i) {
|
||||||
glyph = (uchar)text[i];
|
glyph = (uchar)text[i];
|
||||||
|
|
||||||
// store current glyph topLeft
|
// store current glyph topLeft
|
||||||
|
|
|
@ -42,8 +42,6 @@ enum EAlign {
|
||||||
ALIGN_BOTTOM_LEFT = ALIGN_BOTTOM | ALIGN_LEFT
|
ALIGN_BOTTOM_LEFT = ALIGN_BOTTOM | ALIGN_LEFT
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextArea;
|
|
||||||
|
|
||||||
class Font
|
class Font
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -55,22 +53,19 @@ public:
|
||||||
/// Load font from file
|
/// Load font from file
|
||||||
bool load(const std::string &file);
|
bool load(const std::string &file);
|
||||||
|
|
||||||
/// Simple text render starting at pos
|
/// Simple text render starting at startPos
|
||||||
void renderText(const std::string& text,
|
void renderText(const std::string& text,
|
||||||
const Point& startPos,
|
const Point& startPos,
|
||||||
const Color& color = Color::white);
|
const Color& color = Color::white);
|
||||||
|
|
||||||
/** Advanced text render
|
/// Advanced text render
|
||||||
* screenCoords is the rect that will be filled on the screen
|
|
||||||
* startRenderPosition is the postion to start rendering relative to the text rect
|
|
||||||
*/
|
|
||||||
void renderText(const std::string& text,
|
void renderText(const std::string& text,
|
||||||
const Rect& screenCoords,
|
const Rect& screenCoords,
|
||||||
int align = ALIGN_TOP_LEFT,
|
int align = ALIGN_TOP_LEFT,
|
||||||
const Color& color = Color::white);
|
const Color& color = Color::white);
|
||||||
|
|
||||||
/// Calculate glyphs positions to use on render, also calculates textBoxSize if wanted
|
/// Calculate glyphs positions to use on render, also calculates textBoxSize if wanted
|
||||||
std::vector<Point> calculateGlyphsPositions(const std::string& text, int align = ALIGN_TOP_LEFT, Size *textBoxSize = NULL);
|
const std::vector<Point>& calculateGlyphsPositions(const std::string& text, int align = ALIGN_TOP_LEFT, Size *textBoxSize = NULL) const;
|
||||||
|
|
||||||
/// Simulate render and calculate text size
|
/// Simulate render and calculate text size
|
||||||
Size calculateTextRectSize(const std::string& text);
|
Size calculateTextRectSize(const std::string& text);
|
||||||
|
|
|
@ -48,7 +48,7 @@ void Graphics::init()
|
||||||
|
|
||||||
void Graphics::terminate()
|
void Graphics::terminate()
|
||||||
{
|
{
|
||||||
|
m_bindedTexture = TexturePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Graphics::isExtensionSupported(const char *extension)
|
bool Graphics::isExtensionSupported(const char *extension)
|
||||||
|
@ -88,6 +88,8 @@ void Graphics::resize(const Size& size)
|
||||||
|
|
||||||
void Graphics::restoreViewport()
|
void Graphics::restoreViewport()
|
||||||
{
|
{
|
||||||
|
disableDrawing();
|
||||||
|
|
||||||
const int& width = m_screenSize.width();
|
const int& width = m_screenSize.width();
|
||||||
const int& height = m_screenSize.height();
|
const int& height = m_screenSize.height();
|
||||||
|
|
||||||
|
@ -116,11 +118,23 @@ void Graphics::beginRender()
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
|
// quads is the default drawing mode
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
m_drawMode = DRAW_QUADS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::endRender()
|
void Graphics::endRender()
|
||||||
{
|
{
|
||||||
|
// end last drawing
|
||||||
|
glEnd();
|
||||||
|
m_drawMode = DRAW_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::disableDrawing()
|
||||||
|
{
|
||||||
|
glEnd();
|
||||||
|
m_drawMode = DRAW_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::drawTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords, const Color& color)
|
void Graphics::drawTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords, const Color& color)
|
||||||
|
@ -128,8 +142,6 @@ void Graphics::drawTexturedRect(const Rect& screenCoords, const TexturePtr& text
|
||||||
if(screenCoords.isEmpty())
|
if(screenCoords.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glColor4ubv(color.rgbaPtr());
|
|
||||||
|
|
||||||
// rect correction for opengl
|
// rect correction for opengl
|
||||||
int right = screenCoords.right() + 1;
|
int right = screenCoords.right() + 1;
|
||||||
int bottom = screenCoords.bottom() + 1;
|
int bottom = screenCoords.bottom() + 1;
|
||||||
|
@ -149,15 +161,11 @@ void Graphics::drawTexturedRect(const Rect& screenCoords, const TexturePtr& text
|
||||||
textureLeft = (float)textureCoords.left() / textureSize.width();
|
textureLeft = (float)textureCoords.left() / textureSize.width();
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->getTextureId());
|
bindTexture(texture, color);
|
||||||
glBegin(GL_QUADS);
|
|
||||||
|
|
||||||
glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top);
|
glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top);
|
||||||
glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom);
|
glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom);
|
||||||
glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom);
|
glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom);
|
||||||
glTexCoord2f(textureRight, textureTop); glVertex2i(right, top);
|
glTexCoord2f(textureRight, textureTop); glVertex2i(right, top);
|
||||||
|
|
||||||
glEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords, const Color& color)
|
void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords, const Color& color)
|
||||||
|
@ -193,24 +201,17 @@ void Graphics::drawFilledRect(const Rect& screenCoords, const Color& color)
|
||||||
if(screenCoords.isEmpty())
|
if(screenCoords.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
glColor4ubv(color.rgbaPtr());
|
|
||||||
|
|
||||||
// rect correction for opengl
|
// rect correction for opengl
|
||||||
int right = screenCoords.right() + 1;
|
int right = screenCoords.right() + 1;
|
||||||
int bottom = screenCoords.bottom() + 1;
|
int bottom = screenCoords.bottom() + 1;
|
||||||
int top = screenCoords.top();
|
int top = screenCoords.top();
|
||||||
int left = screenCoords.left();
|
int left = screenCoords.left();
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
bindColor(color);
|
||||||
glVertex2i(left, top);
|
glVertex2i(left, top);
|
||||||
glVertex2i(left, bottom);
|
glVertex2i(left, bottom);
|
||||||
glVertex2i(right, bottom);
|
glVertex2i(right, bottom);
|
||||||
glVertex2i(right, top);
|
glVertex2i(right, top);
|
||||||
glEnd();
|
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,41 +220,71 @@ void Graphics::drawBoundingRect(const Rect& screenCoords, const Color& color, in
|
||||||
if(2 * innerLineWidth > screenCoords.height() || screenCoords.isEmpty())
|
if(2 * innerLineWidth > screenCoords.height() || screenCoords.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
glColor4ubv(color.rgbaPtr());
|
|
||||||
|
|
||||||
// rect correction for opengl
|
// rect correction for opengl
|
||||||
int right = screenCoords.right()+1;
|
int right = screenCoords.right()+1;
|
||||||
int bottom = screenCoords.bottom()+1;
|
int bottom = screenCoords.bottom()+1;
|
||||||
int top = screenCoords.top();
|
int top = screenCoords.top();
|
||||||
int left = screenCoords.left();
|
int left = screenCoords.left();
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
bindColor(color);
|
||||||
// top line
|
|
||||||
glVertex2i(left, top);
|
|
||||||
glVertex2i(left, top + innerLineWidth);
|
|
||||||
glVertex2i(right, top + innerLineWidth);
|
|
||||||
glVertex2i(right, top);
|
|
||||||
|
|
||||||
// left
|
// top line
|
||||||
glVertex2i(left, screenCoords.top() + innerLineWidth);
|
glVertex2i(left, top);
|
||||||
glVertex2i(left, bottom - innerLineWidth);
|
glVertex2i(left, top + innerLineWidth);
|
||||||
glVertex2i(left + innerLineWidth, bottom - innerLineWidth);
|
glVertex2i(right, top + innerLineWidth);
|
||||||
glVertex2i(left + innerLineWidth, screenCoords.top() + innerLineWidth);
|
glVertex2i(right, top);
|
||||||
|
|
||||||
// bottom line
|
// left
|
||||||
glVertex2i(left, bottom);
|
glVertex2i(left, screenCoords.top() + innerLineWidth);
|
||||||
glVertex2i(left, bottom - innerLineWidth);
|
glVertex2i(left, bottom - innerLineWidth);
|
||||||
glVertex2i(right, bottom - innerLineWidth);
|
glVertex2i(left + innerLineWidth, bottom - innerLineWidth);
|
||||||
glVertex2i(right, bottom);
|
glVertex2i(left + innerLineWidth, screenCoords.top() + innerLineWidth);
|
||||||
|
|
||||||
// right line
|
// bottom line
|
||||||
glVertex2i(right , top + innerLineWidth);
|
glVertex2i(left, bottom);
|
||||||
glVertex2i(right , bottom - innerLineWidth);
|
glVertex2i(left, bottom - innerLineWidth);
|
||||||
glVertex2i(right - innerLineWidth, bottom - innerLineWidth);
|
glVertex2i(right, bottom - innerLineWidth);
|
||||||
glVertex2i(right - innerLineWidth, top + innerLineWidth);
|
glVertex2i(right, bottom);
|
||||||
glEnd();
|
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
// right line
|
||||||
|
glVertex2i(right , top + innerLineWidth);
|
||||||
|
glVertex2i(right , bottom - innerLineWidth);
|
||||||
|
glVertex2i(right - innerLineWidth, bottom - innerLineWidth);
|
||||||
|
glVertex2i(right - innerLineWidth, top + innerLineWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::bindColor(const Color& color)
|
||||||
|
{
|
||||||
|
// switch drawing to colored quads
|
||||||
|
if(m_drawMode != DRAW_COLOR_QUADS || m_bindedColor != color) {
|
||||||
|
if(m_drawMode != DRAW_NONE)
|
||||||
|
glEnd();
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
if(m_bindedColor != color) {
|
||||||
|
glColor4ubv(color.rgbaPtr());
|
||||||
|
m_bindedColor = color;
|
||||||
|
}
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
m_drawMode = DRAW_COLOR_QUADS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::bindTexture(const TexturePtr& texture, const Color& color)
|
||||||
|
{
|
||||||
|
// switch drawing to textured quads
|
||||||
|
if(m_drawMode != DRAW_TEXTURE_QUADS || m_bindedTexture != texture) {
|
||||||
|
if(m_drawMode != DRAW_NONE)
|
||||||
|
glEnd();
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
if(m_bindedTexture != texture) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->getTextureId());
|
||||||
|
m_bindedTexture = texture;
|
||||||
|
}
|
||||||
|
if(m_bindedColor != color) {
|
||||||
|
glColor4ubv(color.rgbaPtr());
|
||||||
|
m_bindedColor = color;
|
||||||
|
}
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
m_drawMode = DRAW_TEXTURE_QUADS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,17 @@
|
||||||
|
|
||||||
class Graphics
|
class Graphics
|
||||||
{
|
{
|
||||||
|
enum EDrawMode {
|
||||||
|
DRAW_NONE = 0,
|
||||||
|
DRAW_QUADS = 1,
|
||||||
|
DRAW_TEXTURE = 2,
|
||||||
|
DRAW_COLORED = 4,
|
||||||
|
DRAW_COLOR_QUADS = DRAW_QUADS | DRAW_COLORED,
|
||||||
|
DRAW_TEXTURE_QUADS = DRAW_QUADS | DRAW_TEXTURE | DRAW_COLORED
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Graphics() { }
|
Graphics() : m_drawMode(DRAW_NONE) { }
|
||||||
|
|
||||||
/// Initialize graphics
|
/// Initialize graphics
|
||||||
void init();
|
void init();
|
||||||
|
@ -56,13 +65,23 @@ public:
|
||||||
|
|
||||||
const Size& getScreenSize() const { return m_screenSize; }
|
const Size& getScreenSize() const { return m_screenSize; }
|
||||||
|
|
||||||
|
void disableDrawing();
|
||||||
|
void enableDrawing();
|
||||||
|
|
||||||
void drawTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords = Rect(), const Color& color = Color::white);
|
void drawTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords = Rect(), const Color& color = Color::white);
|
||||||
void drawRepeatedTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords, const Color& color = Color::white);
|
void drawRepeatedTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords, const Color& color = Color::white);
|
||||||
void drawFilledRect(const Rect& screenCoords, const Color& color);
|
void drawFilledRect(const Rect& screenCoords, const Color& color);
|
||||||
void drawBoundingRect(const Rect& screenCoords, const Color& color = Color::green, int innerLineWidth = 1);
|
void drawBoundingRect(const Rect& screenCoords, const Color& color = Color::green, int innerLineWidth = 1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void bindTexture(const TexturePtr& texture, const Color& color = Color::white);
|
||||||
|
void bindColor(const Color& color);
|
||||||
|
|
||||||
|
TexturePtr m_bindedTexture;
|
||||||
|
Color m_bindedColor;
|
||||||
Size m_screenSize;
|
Size m_screenSize;
|
||||||
|
EDrawMode m_drawMode;
|
||||||
|
EDrawMode m_lastDrawMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Graphics g_graphics;
|
extern Graphics g_graphics;
|
||||||
|
|
|
@ -82,22 +82,24 @@ void TextArea::draw()
|
||||||
|
|
||||||
void TextArea::recalculate()
|
void TextArea::recalculate()
|
||||||
{
|
{
|
||||||
// prevent glitches from invalid rects
|
|
||||||
if(!m_screenCoords.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
int textLenght = m_text.length();
|
int textLenght = m_text.length();
|
||||||
|
|
||||||
m_glyphsCoords.clear();
|
// prevent glitches
|
||||||
m_glyphsTexCoords.clear();
|
if(!m_screenCoords.isValid() || !m_font)
|
||||||
m_glyphsCoords.resize(textLenght);
|
return;
|
||||||
m_glyphsTexCoords.resize(textLenght);
|
|
||||||
|
|
||||||
// map glyphs positions
|
// map glyphs positions
|
||||||
Size textBoxSize;
|
Size textBoxSize;
|
||||||
std::vector<Point> glyphsPositions = m_font->calculateGlyphsPositions(m_text, m_align, &textBoxSize);
|
const std::vector<Point>& glyphsPositions = m_font->calculateGlyphsPositions(m_text, m_align, &textBoxSize);
|
||||||
const Rect *glyphsTextureCoords = m_font->getGlyphsTextureCoords();
|
const Rect *glyphsTextureCoords = m_font->getGlyphsTextureCoords();
|
||||||
const Size *glyphsSize = m_font->getGlyphsSize();
|
const Size *glyphsSize = m_font->getGlyphsSize();
|
||||||
|
int glyph;
|
||||||
|
|
||||||
|
// resize just on demand
|
||||||
|
if(textLenght > (int)m_glyphsCoords.size()) {
|
||||||
|
m_glyphsCoords.resize(textLenght);
|
||||||
|
m_glyphsTexCoords.resize(textLenght);
|
||||||
|
}
|
||||||
|
|
||||||
// readjust start view area based on cursor position
|
// readjust start view area based on cursor position
|
||||||
if(m_cursorPos >= 0 && textLenght > 0) {
|
if(m_cursorPos >= 0 && textLenght > 0) {
|
||||||
|
@ -111,7 +113,7 @@ void TextArea::recalculate()
|
||||||
{
|
{
|
||||||
Rect virtualRect(m_startInternalPos, m_screenCoords.size()); // previus rendered virtual rect
|
Rect virtualRect(m_startInternalPos, m_screenCoords.size()); // previus rendered virtual rect
|
||||||
int pos = m_cursorPos - 1; // element before cursor
|
int pos = m_cursorPos - 1; // element before cursor
|
||||||
int glyph = (uchar)m_text[pos]; // glyph of the element before cursor
|
glyph = (uchar)m_text[pos]; // glyph of the element before cursor
|
||||||
Rect glyphRect(glyphsPositions[pos], glyphsSize[glyph]);
|
Rect glyphRect(glyphsPositions[pos], glyphsSize[glyph]);
|
||||||
|
|
||||||
// if the cursor is not on the previus rendered virtual rect we need to update it
|
// if the cursor is not on the previus rendered virtual rect we need to update it
|
||||||
|
@ -148,8 +150,8 @@ void TextArea::recalculate()
|
||||||
m_drawArea.setBottom(m_screenCoords.bottom());
|
m_drawArea.setBottom(m_screenCoords.bottom());
|
||||||
|
|
||||||
for(int i = 0; i < textLenght; ++i) {
|
for(int i = 0; i < textLenght; ++i) {
|
||||||
int glyph = (uchar)m_text[i];
|
glyph = (uchar)m_text[i];
|
||||||
m_glyphsCoords[i] = Rect();
|
m_glyphsCoords[i].clear();
|
||||||
|
|
||||||
// skip invalid glyphs
|
// skip invalid glyphs
|
||||||
if(glyph < 32)
|
if(glyph < 32)
|
||||||
|
@ -218,41 +220,51 @@ void TextArea::recalculate()
|
||||||
|
|
||||||
void TextArea::setFont(Font* font)
|
void TextArea::setFont(Font* font)
|
||||||
{
|
{
|
||||||
m_font = font;
|
if(m_font != font) {
|
||||||
recalculate();
|
m_font = font;
|
||||||
|
recalculate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextArea::setText(const std::string& text)
|
void TextArea::setText(const std::string& text)
|
||||||
{
|
{
|
||||||
m_text = text;
|
if(m_text != text) {
|
||||||
if(m_cursorPos >= 0) {
|
m_text = text;
|
||||||
m_cursorPos = 0;
|
if(m_cursorPos >= 0) {
|
||||||
m_cursorTicks = g_engine.getLastFrameTicks();
|
m_cursorPos = 0;
|
||||||
|
m_cursorTicks = g_engine.getLastFrameTicks();
|
||||||
|
}
|
||||||
|
recalculate();
|
||||||
}
|
}
|
||||||
recalculate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextArea::setScreenCoords(Rect screenCoords)
|
void TextArea::setScreenCoords(const Rect& screenCoords)
|
||||||
{
|
{
|
||||||
m_screenCoords = screenCoords;
|
if(screenCoords != m_screenCoords) {
|
||||||
recalculate();
|
m_screenCoords = screenCoords;
|
||||||
|
recalculate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextArea::setAlign(int align)
|
void TextArea::setAlign(int align)
|
||||||
{
|
{
|
||||||
m_align = align;
|
if(m_align != align) {
|
||||||
recalculate();
|
m_align = align;
|
||||||
|
recalculate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextArea::setCursorPos(int pos)
|
void TextArea::setCursorPos(int pos)
|
||||||
{
|
{
|
||||||
if(pos < 0)
|
if(pos != m_cursorPos) {
|
||||||
m_cursorPos = 0;
|
if(pos < 0)
|
||||||
else if((uint)pos >= m_text.length())
|
m_cursorPos = 0;
|
||||||
m_cursorPos = m_text.length();
|
else if((uint)pos >= m_text.length())
|
||||||
else
|
m_cursorPos = m_text.length();
|
||||||
m_cursorPos = pos;
|
else
|
||||||
recalculate();
|
m_cursorPos = pos;
|
||||||
|
recalculate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextArea::enableCursor(bool enable)
|
void TextArea::enableCursor(bool enable)
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
|
|
||||||
void setFont(Font *font);
|
void setFont(Font *font);
|
||||||
void setText(const std::string& text);
|
void setText(const std::string& text);
|
||||||
void setScreenCoords(Rect screenCoords);
|
void setScreenCoords(const Rect& screenCoords);
|
||||||
void setAlign(int align);
|
void setAlign(int align);
|
||||||
void setColor(const Color& color) { m_color = color; }
|
void setColor(const Color& color) { m_color = color; }
|
||||||
void setCursorPos(int pos);
|
void setCursorPos(int pos);
|
||||||
|
@ -55,8 +55,9 @@ public:
|
||||||
|
|
||||||
const std::string& getText() const { return m_text; }
|
const std::string& getText() const { return m_text; }
|
||||||
|
|
||||||
|
Font *getFont() const { return m_font; }
|
||||||
int getTextPos(Point pos);
|
int getTextPos(Point pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recalculate();
|
void recalculate();
|
||||||
|
|
||||||
|
@ -76,4 +77,6 @@ private:
|
||||||
std::vector<Rect> m_glyphsTexCoords;
|
std::vector<Rect> m_glyphsTexCoords;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<TextArea> TextAreaPtr;
|
||||||
|
|
||||||
#endif // TEXTAREA_H
|
#endif // TEXTAREA_H
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "uielement.h"
|
#include "uielement.h"
|
||||||
#include "uiskins.h"
|
#include "uiskins.h"
|
||||||
#include "uielementskin.h"
|
#include "uielementskin.h"
|
||||||
#include <graphics/graphics.h>
|
#include "graphics/graphics.h"
|
||||||
|
|
||||||
UIElement::UIElement(UI::EElementType type) :
|
UIElement::UIElement(UI::EElementType type) :
|
||||||
UILayout(),
|
UILayout(),
|
||||||
|
@ -35,9 +35,7 @@ UIElement::UIElement(UI::EElementType type) :
|
||||||
m_enabled(true),
|
m_enabled(true),
|
||||||
m_focused(false)
|
m_focused(false)
|
||||||
{
|
{
|
||||||
// set default skin
|
|
||||||
if(type > UI::Container)
|
|
||||||
setSkin(g_uiSkins.getElementSkin(type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIElement::setSkin(const std::string& skinName)
|
bool UIElement::setSkin(const std::string& skinName)
|
||||||
|
@ -48,10 +46,11 @@ bool UIElement::setSkin(const std::string& skinName)
|
||||||
|
|
||||||
void UIElement::setSkin(UIElementSkin* skin)
|
void UIElement::setSkin(UIElementSkin* skin)
|
||||||
{
|
{
|
||||||
|
m_skin = skin;
|
||||||
if(skin && !getRect().isValid()) {
|
if(skin && !getRect().isValid()) {
|
||||||
setSize(skin->getDefaultSize());
|
setSize(skin->getDefaultSize());
|
||||||
|
skin->onSkinApply(this);
|
||||||
}
|
}
|
||||||
m_skin = skin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIElement::render()
|
void UIElement::render()
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
virtual ~UIElementSkin() { }
|
virtual ~UIElementSkin() { }
|
||||||
|
|
||||||
virtual void load(const YAML::Node& node);
|
virtual void load(const YAML::Node& node);
|
||||||
|
virtual void onSkinApply(UIElement *element) { }
|
||||||
virtual void draw(UIElement *element);
|
virtual void draw(UIElement *element);
|
||||||
|
|
||||||
const std::string& getName() const { return m_name; }
|
const std::string& getName() const { return m_name; }
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
#include "prerequisites.h"
|
#include "prerequisites.h"
|
||||||
#include "uielement.h"
|
#include "uielement.h"
|
||||||
|
|
||||||
class Font;
|
|
||||||
|
|
||||||
class UILabel : public UIElement
|
class UILabel : public UIElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -50,9 +50,13 @@ UIElementPtr UILoader::createElementFromId(const std::string& id)
|
||||||
element = UIElementPtr(new UITextEdit);
|
element = UIElementPtr(new UITextEdit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(element)
|
if(element) {
|
||||||
element->setId(elementId);
|
element->setId(elementId);
|
||||||
|
|
||||||
|
// apply default skin
|
||||||
|
element->setSkin(g_uiSkins.getElementSkin(element->getElementType()));
|
||||||
|
}
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
UITextEdit::UITextEdit() :
|
UITextEdit::UITextEdit() :
|
||||||
UIElement(UI::TextEdit)
|
UIElement(UI::TextEdit)
|
||||||
{
|
{
|
||||||
UITextEditSkin *skin = static_cast<UITextEditSkin*>(getSkin());
|
|
||||||
m_textArea.setFont(skin->getFont());
|
|
||||||
m_textArea.enableCursor();
|
m_textArea.enableCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +46,7 @@ void UITextEdit::onInputEvent(const InputEvent& event)
|
||||||
else if(event.keycode == KC_LEFT)
|
else if(event.keycode == KC_LEFT)
|
||||||
m_textArea.moveCursor(false);
|
m_textArea.moveCursor(false);
|
||||||
} else if(event.type == EV_MOUSE_LDOWN) {
|
} else if(event.type == EV_MOUSE_LDOWN) {
|
||||||
|
|
||||||
} else if(event.type == EV_MOUSE_LUP && getRect().contains(event.mousePos)) {
|
} else if(event.type == EV_MOUSE_LUP && getRect().contains(event.mousePos)) {
|
||||||
m_textArea.setCursorPos(m_textArea.getTextPos(event.mousePos));
|
m_textArea.setCursorPos(m_textArea.getTextPos(event.mousePos));
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ public:
|
||||||
|
|
||||||
void setText(const std::string& text);
|
void setText(const std::string& text);
|
||||||
const std::string& getText() const { return m_textArea.getText(); }
|
const std::string& getText() const { return m_textArea.getText(); }
|
||||||
|
|
||||||
TextArea& getTextArea() { return m_textArea; }
|
TextArea& getTextArea() { return m_textArea; }
|
||||||
|
|
||||||
void onLayoutRectChange(const Rect& rect);
|
void onLayoutRectChange(const Rect& rect);
|
||||||
|
|
|
@ -46,6 +46,12 @@ void UITextEditSkin::load(const YAML::Node& node)
|
||||||
m_textMargin = 2;
|
m_textMargin = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UITextEditSkin::onSkinApply(UIElement* element)
|
||||||
|
{
|
||||||
|
UITextEdit *textEdit = static_cast<UITextEdit*>(element);
|
||||||
|
textEdit->getTextArea().setFont(m_font);
|
||||||
|
}
|
||||||
|
|
||||||
void UITextEditSkin::draw(UIElement* element)
|
void UITextEditSkin::draw(UIElement* element)
|
||||||
{
|
{
|
||||||
UIElementSkin::draw(element);
|
UIElementSkin::draw(element);
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
UIElementSkin(name, UI::TextEdit) { }
|
UIElementSkin(name, UI::TextEdit) { }
|
||||||
|
|
||||||
void load(const YAML::Node& node);
|
void load(const YAML::Node& node);
|
||||||
|
void onSkinApply(UIElement *element);
|
||||||
void draw(UIElement *element);
|
void draw(UIElement *element);
|
||||||
|
|
||||||
Font *getFont() const { return m_font; }
|
Font *getFont() const { return m_font; }
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
inline T width() const { return x2 - x1 + 1; }
|
inline T width() const { return x2 - x1 + 1; }
|
||||||
inline T height() const { return y2 - y1 + 1; }
|
inline T height() const { return y2 - y1 + 1; }
|
||||||
inline TSize<T> size() const { return TSize<T>(width(), height()); }
|
inline TSize<T> size() const { return TSize<T>(width(), height()); }
|
||||||
|
inline void clear() { x1 = y1 = 0; x2 = y2 = -1; }
|
||||||
|
|
||||||
inline void setLeft(T pos) { x1 = pos; }
|
inline void setLeft(T pos) { x1 = pos; }
|
||||||
inline void setTop(T pos) { y1 = pos; }
|
inline void setTop(T pos) { y1 = pos; }
|
||||||
|
|
Loading…
Reference in New Issue