performance improvments

This commit is contained in:
Eduardo Bart 2011-04-16 13:08:55 -03:00
parent da6dfea03e
commit 9b02312bf8
16 changed files with 257 additions and 120 deletions

View File

@ -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();

View File

@ -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;
std::vector<Point> Font::calculateGlyphsPositions(const std::string& text, int align, Size *textBoxSize) int textLenght = text.length();
{
int numGlyphs = text.length(); // map glyphs positions
std::vector<Point> glyphsPositions(numGlyphs); Size textBoxSize;
if(numGlyphs == 0) { const std::vector<Point>& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize);
if(textBoxSize)
textBoxSize->setSize(0,0); for(int i = 0; i < textLenght; ++i) {
return glyphsPositions; 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
} }
std::vector<int> lineWidths(numGlyphs); 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);
}
}
const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text, int align, Size *textBoxSize) const
{
// for performance reasons we use statics vectors that are allocated on demand
static std::vector<Point> glyphsPositions(1);
static std::vector<int> lineWidths(1);
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

View File

@ -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);

View File

@ -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,17 +220,14 @@ 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 // top line
glVertex2i(left, top); glVertex2i(left, top);
glVertex2i(left, top + innerLineWidth); glVertex2i(left, top + innerLineWidth);
@ -253,7 +251,40 @@ void Graphics::drawBoundingRect(const Rect& screenCoords, const Color& color, in
glVertex2i(right , bottom - innerLineWidth); glVertex2i(right , bottom - innerLineWidth);
glVertex2i(right - innerLineWidth, bottom - innerLineWidth); glVertex2i(right - innerLineWidth, bottom - innerLineWidth);
glVertex2i(right - innerLineWidth, top + innerLineWidth); glVertex2i(right - innerLineWidth, top + innerLineWidth);
glEnd(); }
glEnable(GL_TEXTURE_2D); 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;
}
} }

View File

@ -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;

View File

@ -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,34 +220,43 @@ void TextArea::recalculate()
void TextArea::setFont(Font* font) void TextArea::setFont(Font* font)
{ {
if(m_font != font) {
m_font = font; m_font = font;
recalculate(); recalculate();
}
} }
void TextArea::setText(const std::string& text) void TextArea::setText(const std::string& text)
{ {
if(m_text != text) {
m_text = text; m_text = text;
if(m_cursorPos >= 0) { if(m_cursorPos >= 0) {
m_cursorPos = 0; m_cursorPos = 0;
m_cursorTicks = g_engine.getLastFrameTicks(); m_cursorTicks = g_engine.getLastFrameTicks();
} }
recalculate(); recalculate();
}
} }
void TextArea::setScreenCoords(Rect screenCoords) void TextArea::setScreenCoords(const Rect& screenCoords)
{ {
if(screenCoords != m_screenCoords) {
m_screenCoords = screenCoords; m_screenCoords = screenCoords;
recalculate(); recalculate();
}
} }
void TextArea::setAlign(int align) void TextArea::setAlign(int align)
{ {
if(m_align != align) {
m_align = align; m_align = align;
recalculate(); recalculate();
}
} }
void TextArea::setCursorPos(int pos) void TextArea::setCursorPos(int pos)
{ {
if(pos != m_cursorPos) {
if(pos < 0) if(pos < 0)
m_cursorPos = 0; m_cursorPos = 0;
else if((uint)pos >= m_text.length()) else if((uint)pos >= m_text.length())
@ -253,6 +264,7 @@ void TextArea::setCursorPos(int pos)
else else
m_cursorPos = pos; m_cursorPos = pos;
recalculate(); recalculate();
}
} }
void TextArea::enableCursor(bool enable) void TextArea::enableCursor(bool enable)

View File

@ -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,6 +55,7 @@ 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:
@ -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

View File

@ -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()

View File

@ -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; }

View File

@ -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:

View File

@ -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;
} }

View File

@ -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();
} }

View File

@ -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);

View File

@ -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);

View File

@ -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; }

View File

@ -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; }