a bunch of stuff

This commit is contained in:
Eduardo Bart 2011-05-11 19:16:11 -03:00
parent 42c1ae090c
commit c6753747fb
63 changed files with 663 additions and 375 deletions

BIN
data/fonts/sans-11px.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

9
data/fonts/sans-11px.yml Normal file
View File

@ -0,0 +1,9 @@
glyph height: 14
glyph spacing: [0, 1]
top margin: 0
image: sans-11px.png
image glyph size: [16, 16]
first glyph: 0
glyph widths:
32: 4

View File

@ -3,6 +3,7 @@ glyph spacing: [1, 4]
top margin: 3
image: tibia-10px-antialised.png
image glyph size: [8, 16]
first glyph: 32
glyph widths:
32: 2

View File

@ -3,6 +3,7 @@ glyph spacing: [1, 1]
top margin: 3
image: tibia-10px-monochrome.png
image glyph size: [8, 16]
first glyph: 32
glyph widths:
32: 2

View File

@ -3,6 +3,7 @@ glyph spacing: [0, 1]
top margin: 3
image: tibia-12px-rounded.png
image glyph size: [16, 16]
first glyph: 32
glyph widths:
32: 4

View File

@ -3,6 +3,7 @@ glyph spacing: [0, 1]
top margin: 1
image: tibia-8px-antialised.png
image glyph size: [8, 8]
first glyph: 32
glyph widths:
32: 2
32: 2

View File

@ -1,8 +1,5 @@
panel#background:
skin:
image: background.png
antialised: true
size: [500, 500]
skin: mainMenuBackground
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top

View File

@ -1,5 +1,5 @@
window#optionsWindow:
title: Info
title: Options
size: [286, 262]
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter

View File

@ -1,5 +1,5 @@
window#messageBoxWindow:
size: [236, 78]
size: [192, 78]
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter

135
data/skins/lightness.yml Normal file
View File

@ -0,0 +1,135 @@
default font: sans-11px
default font color: [0, 115, 234, 255]
buttons:
default:
default size: [96, 22]
font color: [0, 115, 234, 255]
bordered image:
source: lightness/button-up.png
left border: [0,2,2,6]
right border: [22,2,2,6]
top border: [2,0,20,2]
bottom border: [2,8,20,2]
top left corner: [0,0,2,2]
top right corner: [22,0,2,2]
bottom left corner: [0,8,2,2]
bottom right corner: [22,8,2,2]
center: [2,2,20,6]
hover state:
font color: [255, 255, 255, 255]
bordered image:
source: lightness/button-hover.png
left border: [0,2,2,6]
right border: [22,2,2,6]
top border: [2,0,20,2]
bottom border: [2,8,20,2]
top left corner: [0,0,2,2]
top right corner: [22,0,2,2]
bottom left corner: [0,8,2,2]
bottom right corner: [22,8,2,2]
center: [2,2,20,6]
down state:
font color: [255, 0, 132, 255]
bordered image:
source: lightness/button-down.png
left border: [0,2,2,6]
right border: [22,2,2,6]
top border: [2,0,20,2]
bottom border: [2,8,20,2]
top left corner: [0,0,2,2]
top right corner: [22,0,2,2]
bottom left corner: [0,8,2,2]
bottom right corner: [22,8,2,2]
center: [2,2,20,6]
panels:
default:
# the default panel is empty
mainMenuBackground:
image: lightness/background.png
antialised: true
roundedGridPanel:
bordered image:
source: lightness/menupanel.png
left border: [0,2,2,6]
right border: [22,2,2,6]
top border: [2,0,20,2]
bottom border: [2,8,20,2]
top left corner: [0,0,2,2]
top right corner: [22,0,2,2]
bottom left corner: [0,8,2,2]
bottom right corner: [22,8,2,2]
center: [2,2,20,6]
flatPanel:
bordered image:
source: lightness/panel.png
left border: [0,2,2,6]
right border: [22,2,2,6]
top border: [2,0,20,2]
bottom border: [2,8,20,2]
top left corner: [0,0,2,2]
top right corner: [22,0,2,2]
bottom left corner: [0,8,2,2]
bottom right corner: [22,8,2,2]
center: [2,2,20,6]
labels:
default:
font color: [0, 115, 234, 255]
windows:
default:
font color: [80, 80, 80, 255]
head:
text align: left
margin: 8
height: 26
bordered image:
source: lightness/window.png
left border: [0,5,5,22]
right border: [251,5,5,22]
top border: [5,0,246,5]
bottom border: [5,27,246,5]
top left corner: [0,0,5,5]
top right corner: [251,0,5,5]
bottom left corner: [0,27,5,5]
bottom right corner: [251,27,5,5]
center: [5,5,246,22]
body:
bordered image:
source: lightness/window.png
left border: [0,32,2,222]
right border: [254,32,2,222]
bottom border: [2,254,252,2]
bottom left corner: [0,254,2,2]
bottom right corner: [254,254,2,2]
center: [2, 32, 92, 92]
text edits:
default:
default size: [86, 20]
font color: [80, 80, 80, 255]
text margin: 3
bordered image:
source: lightness/button-down.png
left border: [0,2,2,6]
right border: [22,2,2,6]
top border: [2,0,20,2]
bottom border: [2,8,20,2]
top left corner: [0,0,2,2]
top right corner: [22,0,2,2]
bottom left corner: [0,8,2,2]
bottom right corner: [22,8,2,2]
center: [2,2,20,6]
line decorations:
default:
bordered image:
source: lightness/window.png
top border: [2,254,252,2]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

View File

@ -1,9 +1,11 @@
default skin image: tibiaskin.png
default font: tibia-10px-antialised
default font color: [191, 191, 191, 255]
default texture: tibiaskin/skin.png
buttons:
default:
font: tibia-8px-antialised
text color: [238, 238, 238, 255]
font color: [238, 238, 238, 255]
default size: [86, 20]
bordered image:
@ -33,6 +35,10 @@ panels:
default:
# the default panel is empty
mainMenuBackground:
image: tibiaskin/background.png
antialised: true
roundedGridPanel:
bordered image:
left border: [0,214,5,32]
@ -59,15 +65,12 @@ panels:
labels:
default:
font: tibia-10px-antialised
text color: [191, 191, 191, 255]
windows:
default:
font color: [143, 143, 143, 255]
head:
text color: [143, 143, 143, 255]
height: 17
font: tibia-10px-antialised
bordered image:
left border: [106,187,4,9]
right border: [110,187,4,9]
@ -90,7 +93,6 @@ windows:
text edits:
default:
default size: [86, 16]
font: tibia-10px-antialised
text margin: 3
bordered image:
left border: [308,97,1,1]

View File

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

46
src/framework/constants.h Normal file
View File

@ -0,0 +1,46 @@
/* The MIT License
*
* Copyright (c) 2010 OTClient, https://github.com/edubart/otclient
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CONSTANTS_H
#define CONSTANTS_H
enum AlignmentFlag {
AlignLeft = 1,
AlignRight = 2,
AlignTop = 4,
AlignBottom = 8,
AlignHorizontalCenter = 16,
AlignVerticalCenter = 32,
AlignTopLeft = AlignTop | AlignLeft,
AlignTopRight = AlignTop | AlignRight,
AlignBottomLeft = AlignBottom | AlignLeft,
AlignBottomRight = AlignBottom | AlignRight,
AlignLeftCenter = AlignLeft | AlignVerticalCenter,
AlignRightCenter = AlignRight | AlignVerticalCenter,
AlignTopCenter = AlignTop | AlignHorizontalCenter,
AlignBottomCenter = AlignBottom | AlignHorizontalCenter,
AlignCenter = AlignVerticalCenter | AlignHorizontalCenter
};
#endif // CONSTANTS_H

View File

@ -82,12 +82,12 @@ void Configs::setValue(const std::string &key, const char *value)
void Configs::setValue(const std::string &key, int value)
{
setValue(key, convertType<std::string, int>(value));
setValue(key, convert_cast<std::string>(value));
}
void Configs::setValue(const std::string &key, float value)
{
setValue(key, convertType<std::string, float>(value));
setValue(key, convert_cast<std::string>(value));
}
void Configs::setValue(const std::string &key, bool value)
@ -116,7 +116,7 @@ float Configs::getFloat(const std::string &key) const
flogWarning("WARNING: Config value %s not found", key.c_str());
return 0;
}
return convertType<float, std::string>(it->second);
return convert_cast<float>(it->second);
}
bool Configs::getBoolean(const std::string &key) const
@ -136,5 +136,5 @@ int Configs::getInteger(const std::string &key) const
flogWarning("WARNING: Config value %s not found", key.c_str());
return 0;
}
return convertType<int, std::string>(it->second);
return convert_cast<int>(it->second);
}

View File

@ -31,6 +31,7 @@
#include <ui/uicontainer.h>
#include <net/connection.h>
#include <script/luascript.h>
#include <ui/uiskins.h>
Engine g_engine;
@ -38,23 +39,24 @@ void Engine::init()
{
// initialize stuff
g_graphics.init();
g_fonts.init("tibia-12px-rounded");
g_fonts.init();
g_lua.init();
}
void Engine::terminate()
{
// terminate stuff
g_fonts.terminate();
g_graphics.terminate();
// destroy root ui
UIContainer::getRoot()->destroy();
// cleanup script stuff
g_lua.terminate();
// poll remaning events
g_engine.poll();
// terminate stuff
g_fonts.terminate();
g_graphics.terminate();
}
void Engine::poll()
@ -78,7 +80,7 @@ void Engine::run()
std::string fpsText;
Size fpsTextSize;
Font *defaultFont = g_fonts.getDefaultFont();
FontPtr defaultFont = g_uiSkins.getDefaultFont();
m_lastFrameTicks = Platform::getTicks();
int lastFpsTicks = m_lastFrameTicks;
@ -93,7 +95,7 @@ void Engine::run()
// render only when visible
if(Platform::isWindowVisible()) {
// calculate and fps
// calculate fps
if(m_calculateFps) {
frameCount++;
if(m_lastFrameTicks - lastFpsTicks >= 1000) {
@ -102,7 +104,7 @@ void Engine::run()
frameCount = 0;
// update fps text
fpsText = f("FPS: %d", fps);
fpsText = fmt("FPS: %d", fps);
fpsTextSize = defaultFont->calculateTextRectSize(fpsText);
}
}

View File

@ -75,14 +75,21 @@ void BorderedImage::setTexCoords(const Rect& left,
m_bottomRightCornerTexCoords = bottomRight;
m_centerTexCoords = center;
m_cornersSize = Size(left.width() + right.width(),
m_bordersSize = Size(left.width() + right.width(),
top.height() + bottom.height());
m_defaultSize = Size(std::max(std::max(topLeft.width(), bottomLeft.width()), left.width()) +
std::max(std::max(topRight.width(), bottomRight.width()), right.width()) +
center.width(),
std::max(std::max(topLeft.height(), topRight.height()), top.height()) +
std::max(std::max(bottomLeft.height(), bottomRight.height()), bottom.height()) +
center.height());
}
void BorderedImage::draw(const Rect& screenCoords)
{
Rect rectCoords;
Size centerSize = screenCoords.size() - m_cornersSize;
Size centerSize = screenCoords.size() - m_bordersSize;
// first the center
if(centerSize.area() > 0) {
@ -144,3 +151,4 @@ void BorderedImage::draw(const Rect& screenCoords)
m_bottomRightCornerTexCoords.size());
g_graphics.drawTexturedRect(rectCoords, m_texture, m_bottomRightCornerTexCoords);
}

View File

@ -66,6 +66,8 @@ public:
void draw(const Rect& screenCoords);
Size getDefaultSize() const { return m_defaultSize; }
private:
Rect m_leftBorderTexCoords;
Rect m_rightBorderTexCoords;
@ -79,7 +81,8 @@ private:
Rect m_centerTexCoords;
Size m_cornersSize;
Size m_bordersSize;
Size m_defaultSize;
};
typedef boost::shared_ptr<BorderedImage> BorderedImagePtr;

View File

@ -34,9 +34,9 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
uchar *texturePixels = m_texture->getPixels();
// small AI to auto calculate pixels widths
for(int glyph = 32; glyph< 256; ++glyph) {
Rect glyphCoords(((glyph - 32) % numHorizontalGlyphs) * glyphSize.width(),
((glyph - 32) / numHorizontalGlyphs) * glyphSize.height(),
for(int glyph = m_firstGlyph; glyph< 256; ++glyph) {
Rect glyphCoords(((glyph - m_firstGlyph) % numHorizontalGlyphs) * glyphSize.width(),
((glyph - m_firstGlyph) / numHorizontalGlyphs) * glyphSize.height(),
glyphSize.width(),
m_glyphHeight);
int width = glyphSize.width();
@ -85,13 +85,11 @@ bool Font::load(const std::string& file)
// required values
doc["glyph height"] >> m_glyphHeight;
doc["image glyph size"] >> glyphSize;
doc["image"] >> textureName;
// optional values
if(doc.FindValue("glyph spacing"))
doc["glyph spacing"] >> m_glyphSpacing;
if(doc.FindValue("top margin"))
doc["top margin"] >> m_topMargin;
textureName = yamlRead<std::string>(doc, "image");
m_glyphHeight = yamlRead<int>(doc, "glyph height");
m_firstGlyph = yamlRead<int>(doc, "first glyph", 32);
m_topMargin = yamlRead<int>(doc, "top margin", 0);
m_glyphSpacing = yamlRead(doc, "glyph spacing", Size(0,0));
// load texture
m_texture = g_textures.get("fonts/" + textureName);
@ -104,21 +102,15 @@ bool Font::load(const std::string& file)
calculateGlyphsWidthsAutomatically(glyphSize);
// read custom widths
if(doc.FindValue("glyph widths")) {
const YAML::Node& widthsNode = doc["glyph widths"];
for(auto it = widthsNode.begin(); it != widthsNode.end(); ++it) {
int glyph, glyphWidth;
it.first() >> glyph;
it.second() >> glyphWidth;
m_glyphsSize[glyph].setWidth(glyphWidth);
}
}
std::map<int, int> glyphWidths = yamlReadMap<int, int>(doc, "glyph widths");
foreach(const auto& pair, glyphWidths)
m_glyphsSize[pair.first].setWidth(pair.second);
// calculate glyphs texture coords
int numHorizontalGlyphs = m_texture->getSize().width() / glyphSize.width();
for(int glyph = 32; glyph< 256; ++glyph) {
m_glyphsTextureCoords[glyph].setRect(((glyph - 32) % numHorizontalGlyphs) * glyphSize.width(),
((glyph - 32) / numHorizontalGlyphs) * glyphSize.height(),
for(int glyph = m_firstGlyph; glyph< 256; ++glyph) {
m_glyphsTextureCoords[glyph].setRect(((glyph - m_firstGlyph) % numHorizontalGlyphs) * glyphSize.width(),
((glyph - m_firstGlyph) / numHorizontalGlyphs) * glyphSize.height(),
m_glyphsSize[glyph].width(),
m_glyphHeight);
}
@ -136,13 +128,13 @@ void Font::renderText(const std::string& text,
{
Size boxSize = g_graphics.getScreenSize() - startPos.toSize();
Rect screenCoords(startPos, boxSize);
renderText(text, screenCoords, ALIGN_TOP_LEFT, color);
renderText(text, screenCoords, AlignTopLeft, color);
}
void Font::renderText(const std::string& text,
const Rect& screenCoords,
int align,
AlignmentFlag align,
const Color& color)
{
// prevent glitches from invalid rects
@ -167,19 +159,19 @@ void Font::renderText(const std::string& text,
Rect glyphTextureCoords = m_glyphsTextureCoords[glyph];
// first translate to align position
if(align & ALIGN_BOTTOM) {
if(align & AlignBottom) {
glyphScreenCoords.translate(0, screenCoords.height() - textBoxSize.height());
} else if(align & ALIGN_VERTICAL_CENTER) {
} else if(align & AlignVerticalCenter) {
glyphScreenCoords.translate(0, (screenCoords.height() - textBoxSize.height()) / 2);
} else { // ALIGN_TOP
} else { // AlignTop
// nothing to do
}
if(align & ALIGN_RIGHT) {
if(align & AlignRight) {
glyphScreenCoords.translate(screenCoords.width() - textBoxSize.width(), 0);
} else if(align & ALIGN_HORIZONTAL_CENTER) {
} else if(align & AlignHorizontalCenter) {
glyphScreenCoords.translate((screenCoords.width() - textBoxSize.width()) / 2, 0);
} else { // ALIGN_TOP
} else { // AlignLeft
// nothing to do
}
@ -205,7 +197,7 @@ void Font::renderText(const std::string& text,
}
}
const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text, int align, Size *textBoxSize) const
const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text, AlignmentFlag align, Size *textBoxSize) const
{
// for performance reasons we use statics vectors that are allocated on demand
static std::vector<Point> glyphsPositions(1);
@ -229,7 +221,7 @@ const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text
glyphsPositions.resize(textLength);
// calculate lines width
if((align & ALIGN_RIGHT || align & ALIGN_HORIZONTAL_CENTER) || textBoxSize) {
if((align & AlignRight || align & AlignHorizontalCenter) || textBoxSize) {
lineWidths[0] = 0;
for(i = 0; i< textLength; ++i) {
glyph = (uchar)text[i];
@ -259,11 +251,11 @@ const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text
}
// calculate start x pos
if(align & ALIGN_RIGHT) {
if(align & AlignRight) {
virtualPos.x = (maxLineWidth - lineWidths[lines]);
} else if(align & ALIGN_HORIZONTAL_CENTER) {
} else if(align & AlignHorizontalCenter) {
virtualPos.x = (maxLineWidth - lineWidths[lines]) / 2;
} else { // ALIGN_LEFT
} else { // AlignLeft
virtualPos.x = 0;
}
}
@ -288,7 +280,7 @@ const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text
Size Font::calculateTextRectSize(const std::string& text)
{
Size size;
calculateGlyphsPositions(text, ALIGN_TOP_LEFT, &size);
calculateGlyphsPositions(text, AlignTopLeft, &size);
return size;
}

View File

@ -28,27 +28,11 @@
#include <prerequisites.h>
#include <graphics/texture.h>
enum EAlign {
ALIGN_TOP = 1 << 0,
ALIGN_BOTTOM = 1 << 1,
ALIGN_LEFT = 1 << 2,
ALIGN_RIGHT = 1 << 3,
ALIGN_HORIZONTAL_CENTER = 1 << 4,
ALIGN_VERTICAL_CENTER = 1 << 5,
ALIGN_CENTER = ALIGN_HORIZONTAL_CENTER | ALIGN_VERTICAL_CENTER,
ALIGN_TOP_RIGHT = ALIGN_TOP | ALIGN_RIGHT,
ALIGN_TOP_LEFT = ALIGN_TOP | ALIGN_LEFT,
ALIGN_BOTTOM_RIGHT = ALIGN_BOTTOM | ALIGN_RIGHT,
ALIGN_BOTTOM_LEFT = ALIGN_BOTTOM | ALIGN_LEFT
};
class Font
{
public:
Font(const std::string& name) :
m_name(name),
m_glyphHeight(10),
m_topMargin(0) { }
m_name(name) { }
/// Load font from file
bool load(const std::string &file);
@ -61,28 +45,29 @@ public:
/// Advanced text render
void renderText(const std::string& text,
const Rect& screenCoords,
int align = ALIGN_TOP_LEFT,
AlignmentFlag align = AlignTopLeft,
const Color& color = Color::white);
/// Calculate glyphs positions to use on render, also calculates textBoxSize if wanted
const std::vector<Point>& calculateGlyphsPositions(const std::string& text, int align = ALIGN_TOP_LEFT, Size *textBoxSize = NULL) const;
const std::vector<Point>& calculateGlyphsPositions(const std::string& text, AlignmentFlag align = AlignTopLeft, Size *textBoxSize = NULL) const;
/// Simulate render and calculate text size
Size calculateTextRectSize(const std::string& text);
const std::string& getName() const { return m_name; }
std::string getName() const { return m_name; }
int getGlyphHeight() const { return m_glyphHeight; }
const Rect *getGlyphsTextureCoords() const { return m_glyphsTextureCoords; }
const Size *getGlyphsSize() const { return m_glyphsSize; }
const TexturePtr& getTexture() const { return m_texture; }
int getTopMargin() const { return m_topMargin; }
const Size& getGlyphSpacing() const { return m_glyphSpacing; }
Size getGlyphSpacing() const { return m_glyphSpacing; }
private:
void calculateGlyphsWidthsAutomatically(const Size& glyphSize);
std::string m_name;
int m_glyphHeight;
int m_firstGlyph;
int m_topMargin;
Size m_glyphSpacing;
TexturePtr m_texture;

View File

@ -28,7 +28,7 @@
Fonts g_fonts;
void Fonts::init(const std::string& defaultFontName)
void Fonts::init()
{
// load all fonts
std::list<std::string> files = g_resources.getDirectoryFiles("fonts");
@ -37,27 +37,21 @@ void Fonts::init(const std::string& defaultFontName)
std::string name = file;
boost::erase_first(name, ".yml");
FontPtr font(new Font(name));
if(font->load("fonts/" + file)) {
if(font->load("fonts/" + file))
m_fonts.push_back(font);
if(name == defaultFontName)
m_defaultFont = font;
}
}
}
if(!m_defaultFont)
flogFatal("FATAL ERROR: Could not load the default font \"%s\"\n", defaultFontName.c_str());
}
Font* Fonts::get(const std::string& fontName)
FontPtr Fonts::get(const std::string& fontName)
{
// find font by name
for(auto it = m_fonts.begin(); it != m_fonts.end(); ++it) {
if((*it)->getName() == fontName)
return (*it).get();
foreach(const FontPtr& font, m_fonts) {
if(font->getName() == fontName)
return font;
}
flogError("ERROR: Font \"%s\" not found, returing the default one", fontName.c_str());
return m_defaultFont.get();
flogFatal("ERROR: Font \"%s\" not found", fontName.c_str());
return FontPtr();
}

View File

@ -34,20 +34,16 @@ public:
Fonts() { }
/// Initialize all fonts
void init(const std::string& defaultFontName);
void init();
/// Terminate all fonts
void terminate() { }
/// Get a font by name
Font *get(const std::string& fontName);
/// Get the default font
Font *getDefaultFont() { return m_defaultFont.get(); };
FontPtr get(const std::string& fontName);
private:
std::vector<FontPtr> m_fonts;
FontPtr m_defaultFont;
};
extern Fonts g_fonts;

View File

@ -40,6 +40,7 @@ void Graphics::init()
glEnable(GL_TEXTURE_2D); // enable textures by default
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
@ -266,7 +267,7 @@ void Graphics::bindColor(const Color& color)
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_TEXTURE_QUADS || m_bindedTexture != texture || m_bindedColor != color) {
if(m_drawMode != DRAW_NONE)
glEnd();
glEnable(GL_TEXTURE_2D);

View File

@ -30,7 +30,7 @@
class Graphics
{
enum EDrawMode {
enum DrawMode {
DRAW_NONE = 0,
DRAW_QUADS = 1,
DRAW_TEXTURE = 2,
@ -80,8 +80,7 @@ private:
TexturePtr m_bindedTexture;
Color m_bindedColor;
Size m_screenSize;
EDrawMode m_drawMode;
EDrawMode m_lastDrawMode;
DrawMode m_drawMode;
};
extern Graphics g_graphics;

View File

@ -28,8 +28,7 @@
#include <graphics/graphics.h>
TextArea::TextArea() :
m_font(0),
m_align(ALIGN_TOP_LEFT),
m_align(AlignLeftCenter),
m_color(Color::white),
m_cursorPos(-1),
m_startRenderPos(0),
@ -37,10 +36,10 @@ TextArea::TextArea() :
{
}
TextArea::TextArea(Font* font,
TextArea::TextArea(FontPtr font,
const std::string& text,
const Rect& screenCoords,
int align,
AlignmentFlag align,
const Color& color) :
m_font(font),
m_text(text),
@ -165,19 +164,19 @@ void TextArea::recalculate()
Rect glyphTextureCoords = glyphsTextureCoords[glyph];
// first translate to align position
if(m_align & ALIGN_BOTTOM) {
if(m_align & AlignBottom) {
glyphScreenCoords.translate(0, m_screenCoords.height() - textBoxSize.height());
} else if(m_align & ALIGN_VERTICAL_CENTER) {
} else if(m_align & AlignVerticalCenter) {
glyphScreenCoords.translate(0, (m_screenCoords.height() - textBoxSize.height()) / 2);
} else { // ALIGN_TOP
} else { // AlignTop
// nothing to do
}
if(m_align & ALIGN_RIGHT) {
if(m_align & AlignRight) {
glyphScreenCoords.translate(m_screenCoords.width() - textBoxSize.width(), 0);
} else if(m_align & ALIGN_HORIZONTAL_CENTER) {
} else if(m_align & AlignHorizontalCenter) {
glyphScreenCoords.translate((m_screenCoords.width() - textBoxSize.width()) / 2, 0);
} else { // ALIGN_TOP
} else { // AlignLeft
// nothing to do
}
@ -221,7 +220,7 @@ void TextArea::recalculate()
}
}
void TextArea::setFont(Font* font)
void TextArea::setFont(FontPtr font)
{
if(m_font != font) {
m_font = font;
@ -249,7 +248,7 @@ void TextArea::setScreenCoords(const Rect& screenCoords)
}
}
void TextArea::setAlign(int align)
void TextArea::setAlign(AlignmentFlag align)
{
if(m_align != align) {
m_align = align;

View File

@ -32,18 +32,18 @@ class TextArea
{
public:
TextArea();
TextArea(Font *font,
TextArea(FontPtr font,
const std::string& text,
const Rect& screenCoords,
int align = ALIGN_TOP_LEFT,
AlignmentFlag align = AlignTopLeft,
const Color& color = Color::white);
void draw();
void setFont(Font *font);
void setFont(FontPtr font);
void setText(const std::string& text);
void setScreenCoords(const Rect& screenCoords);
void setAlign(int align);
void setAlign(AlignmentFlag align);
void setColor(const Color& color) { m_color = color; }
void setCursorPos(int pos);
void enableCursor(bool enable = true);
@ -55,17 +55,17 @@ public:
std::string getText() const { return m_text; }
Font *getFont() const { return m_font; }
FontPtr getFont() const { return m_font; }
int getTextPos(Point pos);
private:
void recalculate();
Font *m_font;
FontPtr m_font;
std::string m_text;
Rect m_screenCoords;
Rect m_drawArea;
int m_align;
AlignmentFlag m_align;
Color m_color;
int m_cursorPos;
Point m_startInternalPos;

View File

@ -45,7 +45,7 @@ void Connection::connect(const std::string& host, uint16 port, const SimpleCallb
m_connectCallback = callback;
m_connectionState = CONNECTION_STATE_RESOLVING;
boost::asio::ip::tcp::resolver::query query(host, convertType<std::string, uint16>(port));
boost::asio::ip::tcp::resolver::query query(host, convert_cast<std::string>(port));
m_resolver.async_resolve(query, boost::bind(&Connection::onResolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator));
m_timer.expires_from_now(boost::posix_time::seconds(2));

View File

@ -74,8 +74,8 @@ typedef int8_t int8;
typedef boost::function<void()> SimpleCallback;
// yaml
#include <yaml-cpp/yaml.h>
// constants
#include <constants.h>
// common utilities
#include <util/util.h>
@ -84,5 +84,6 @@ typedef boost::function<void()> SimpleCallback;
#include <util/point.h>
#include <util/size.h>
#include <util/rect.h>
#include <util/yaml.h>
#endif // PREREQUISITES_H

View File

@ -187,7 +187,7 @@ void LuaScript::setMetatable(const std::string& name, int index)
{
luaL_getmetatable(L, name.c_str());
if(isNil())
reportError(f("could not retrive metatable %d", name));
reportError(fmt("could not retrive metatable %d", name));
else
lua_setmetatable(L, index < 0 ? index-1 : index);
}

View File

@ -66,7 +66,7 @@ void Scriptable::callLuaTableField(const std::string& field)
g_lua.pop();
}
} else if(!g_lua.isNil()) {
g_lua.reportError(f("field '%s' for '%s' is not a valid function or array of functions", field % getScriptableName()));
g_lua.reportError(fmt("field '%s' for '%s' is not a valid function or array of functions", field % getScriptableName()));
}
// release self

View File

@ -25,6 +25,7 @@
#include <prerequisites.h>
#include <core/dispatcher.h>
#include <ui/uibutton.h>
#include "uicontainer.h"
void UIButton::onInputEvent(const InputEvent& event)
{
@ -35,5 +36,10 @@ void UIButton::onInputEvent(const InputEvent& event)
if(getRect().contains(event.mousePos)) {
g_dispatcher.addTask(boost::bind(&Scriptable::callLuaTableField, shared_from_this(), "onClick"));
}
} else if(event.type == EV_MOUSE_MOVE && m_state != ButtonDown) {
if(getRect().contains(event.mousePos) && UIContainer::getRoot()->recursiveGetChildByPos(event.mousePos) == asUIElement())
m_state = ButtonMouseOver;
else
m_state = ButtonUp;
}
}

View File

@ -31,17 +31,21 @@ void UIButtonSkin::load(const YAML::Node& node)
{
UIElementSkin::load(node);
m_buttonDownImage = loadImage(node["down state"]);
m_buttonDownTextColor = getFontColor();
m_buttonHoverTextColor = getFontColor();
if(node["down state"].FindValue("text translate"))
node["down state"]["text translate"] >> m_buttonDownTranslate;
if(yamlHasValue(node, "down state")) {
const YAML::Node& cnode = node["down state"];
m_buttonDownImage = loadImage(cnode);
m_buttonDownTranslate = yamlRead(cnode, "text translate", Point());
m_buttonDownTextColor = yamlRead(cnode, "font color", getFontColor());
}
if(node.FindValue("mouse over state"))
m_buttonHoverImage = loadImage(node["mouse over state"]);
m_font = g_fonts.get(node["font"].Read<std::string>());
node["text color"] >> m_textColor;
if(yamlHasValue(node, "hover state")) {
const YAML::Node& cnode = node["hover state"];
m_buttonHoverImage = loadImage(cnode);
m_buttonHoverTextColor = yamlRead(cnode, "font color", getFontColor());
}
}
void UIButtonSkin::draw(UIElement *element)
@ -59,5 +63,10 @@ void UIButtonSkin::draw(UIElement *element)
UIElementSkin::draw(element);
}
m_font->renderText(button->getText(), textRect, ALIGN_CENTER, m_textColor);
Color textColor = getFontColor();
if(button->getState() == UIButton::ButtonDown)
textColor = m_buttonDownTextColor;
else if(button->getState() == UIButton::ButtonMouseOver)
textColor = m_buttonHoverTextColor;
getFont()->renderText(button->getText(), textRect, AlignCenter, textColor);
}

View File

@ -44,8 +44,8 @@ private:
ImagePtr m_buttonDownImage;
ImagePtr m_buttonHoverImage;
Point m_buttonDownTranslate;
Font *m_font;
Color m_textColor;
Color m_buttonDownTextColor;
Color m_buttonHoverTextColor;
};
#endif // UIBUTTONSKIN_H

View File

@ -106,17 +106,6 @@ UIElementPtr UIContainer::getChildById(const std::string& id)
return UIElementPtr();
}
UIElementPtr UIContainer::getChildByPos(const Point& pos)
{
for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
const UIElementPtr& element = (*it);
if(element->getRect().contains(pos))
return element;
}
return UIElementPtr();
}
UIElementPtr UIContainer::recursiveGetChildById(const std::string& id)
{
if(getId() == id || id == "self")
@ -144,6 +133,35 @@ UIElementPtr UIContainer::recursiveGetChildById(const std::string& id)
return UIElementPtr();
}
UIElementPtr UIContainer::getChildByPos(const Point& pos)
{
for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
const UIElementPtr& element = (*it);
if(element->getRect().contains(pos))
return element;
}
return UIElementPtr();
}
UIElementPtr UIContainer::recursiveGetChildByPos(const Point& pos)
{
for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
const UIElementPtr& element = (*it);
if(element->getRect().contains(pos)) {
if(UIContainerPtr container = element->asUIContainer()) {
if(UIElementPtr containerChild = container->recursiveGetChildByPos(pos))
return containerChild;
else
return container;
}
return element;
}
}
return UIElementPtr();
}
void UIContainer::pushChildToTop(const UIElementPtr& child)
{
auto it = std::find(m_children.begin(), m_children.end(), child);
@ -227,12 +245,13 @@ void UIContainer::focusNextElement()
void UIContainer::setFocusedElement(const UIElementPtr& focusedElement)
{
if(focusedElement != m_focusedElement) {
if(m_focusedElement)
m_focusedElement->onFocusChange();
UIElementPtr oldFocused = m_focusedElement;
m_focusedElement = focusedElement;
if(m_focusedElement)
m_focusedElement->onFocusChange();
if(oldFocused)
oldFocused->onFocusChange();
if(focusedElement)
focusedElement->onFocusChange();
}
// when containers are focused they go to the top

View File

@ -48,10 +48,12 @@ public:
bool hasChild(const UIElementPtr& child);
/// Find an element in this container by id
UIElementPtr getChildById(const std::string& id);
/// Find an element by position
UIElementPtr getChildByPos(const Point& pos);
/// Find an element in this container and in its children by id
UIElementPtr recursiveGetChildById(const std::string& id);
/// Find an element by position
UIElementPtr getChildByPos(const Point& pos);
/// Find an element in this container and in its children by position
UIElementPtr recursiveGetChildByPos(const Point& pos);
/// Get children
const std::list<UIElementPtr>& getChildren() const { return m_children; }
/// Pushs a child to the top

View File

@ -28,12 +28,14 @@
#include <ui/uielementskin.h>
#include <graphics/borderedimage.h>
#include <graphics/textures.h>
#include <graphics/fonts.h>
void UIElementSkin::load(const YAML::Node& node)
{
if(node.FindValue("default size"))
node["default size"] >> m_defaultSize;
m_defaultSize = yamlRead(node, "default size", Size());
m_defaultImage = loadImage(node);
m_font = loadFont(node);
m_fontColor = yamlRead(node, "font color", g_uiSkins.getDefaultFontColor());
}
void UIElementSkin::apply(UIElement* element)
@ -47,40 +49,29 @@ void UIElementSkin::draw(UIElement *element)
if(m_defaultImage)
m_defaultImage->draw(element->getRect());
}
ImagePtr UIElementSkin::loadImage(const YAML::Node& node)
{
ImagePtr image;
TexturePtr texture;
if(node.FindValue("bordered image")) {
const YAML::Node& child = node["bordered image"];
Rect left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight, center;
if(child.FindValue("left border"))
child["left border"] >> left;
if(child.FindValue("right border"))
child["right border"] >> right;
if(child.FindValue("top border"))
child["top border"] >> top;
if(child.FindValue("bottom border"))
child["bottom border"] >> bottom;
if(child.FindValue("top left corner"))
child["top left corner"] >> topLeft;
if(child.FindValue("top right corner"))
child["top right corner"] >> topRight;
if(child.FindValue("bottom left corner"))
child["bottom left corner"] >> bottomLeft;
if(child.FindValue("bottom right corner"))
child["bottom right corner"] >> bottomRight;
if(child.FindValue("center"))
child["center"] >> center;
if(yamlHasValue(node, "bordered image")) {
const YAML::Node& cnode = node["bordered image"];
Rect left = yamlRead(cnode, "left border", Rect());
Rect right = yamlRead(cnode, "right border", Rect());
Rect top = yamlRead(cnode, "top border", Rect());
Rect bottom = yamlRead(cnode, "bottom border", Rect());
Rect topLeft = yamlRead(cnode, "top left corner", Rect());
Rect topRight = yamlRead(cnode, "top right corner", Rect());
Rect bottomLeft = yamlRead(cnode, "bottom left corner", Rect());
Rect bottomRight = yamlRead(cnode, "bottom right corner", Rect());
Rect center = yamlRead(cnode, "center", Rect());
std::string textureName = yamlRead(cnode, "source", std::string());
if(child.FindValue("image")) {
std::string textureName;
child["image"] >> textureName;
texture = g_textures.get(textureName);
} else {
if(!textureName.empty())
texture = g_textures.get("skins/" + textureName);
else
texture = g_uiSkins.getDefaultTexture();
}
if(texture) {
image = ImagePtr(new BorderedImage(texture,
@ -94,18 +85,20 @@ ImagePtr UIElementSkin::loadImage(const YAML::Node& node)
bottomRight,
center));
}
} else if(node.FindValue("image")) {
std::string textureName;
node["image"] >> textureName;
texture = g_textures.get(textureName);
if(texture) {
if(!image)
logError(yamlErrorDesc(cnode, "failed to load bordered image"));
} else if(yamlHasValue(node, "image")) {
texture = g_textures.get("skins/" + yamlRead<std::string>(node, "image"));
if(texture)
image = ImagePtr(new Image(texture));
}
if(!image)
logError(yamlErrorDesc(node["image"], "failed to load image"));
}
if(texture && node.FindValue("antialised")){
bool antialised;
node["antialised"] >> antialised;
if(texture) {
bool antialised = yamlRead(node, "antialised", false);
if(antialised)
texture->enableBilinearFilter();
}
@ -113,3 +106,14 @@ ImagePtr UIElementSkin::loadImage(const YAML::Node& node)
return image;
}
FontPtr UIElementSkin::loadFont(const YAML::Node& node)
{
FontPtr font;
if(yamlHasValue(node, "font"))
font = g_fonts.get(yamlRead<std::string>(node, "font"));
if(!font)
font = g_uiSkins.getDefaultFont();
return font;
}

View File

@ -28,6 +28,7 @@
#include <prerequisites.h>
#include <graphics/image.h>
#include <ui/uiconstants.h>
#include <graphics/font.h>
class UIElement;
@ -51,15 +52,20 @@ public:
const Size& getDefaultSize() const { return m_defaultSize; }
UI::ElementType getElementType() const { return m_elementType; }
ImagePtr getDefaultImage() const { return m_defaultImage; }
FontPtr getFont() const { return m_font; }
Color getFontColor() const { return m_fontColor; }
protected:
ImagePtr loadImage(const YAML::Node& node);
FontPtr loadFont(const YAML::Node &node);
private:
std::string m_name;
UI::ElementType m_elementType;
Size m_defaultSize;
ImagePtr m_defaultImage;
FontPtr m_font;
Color m_fontColor;
};
typedef boost::shared_ptr<UIElementSkin> UIElementSkinPtr;

View File

@ -34,20 +34,20 @@ class UILabel : public UIElement
public:
UILabel() :
UIElement(UI::Label),
m_align(ALIGN_TOP_LEFT),
m_align(AlignTopLeft),
m_color(Color::white) { }
void setText(const std::string& text);
std::string getText() const { return m_text; }
void setAlign(int align) { m_align = align; }
int getAlign() const { return m_align; }
void setAlign(AlignmentFlag align) { m_align = align; }
AlignmentFlag getAlign() const { return m_align; }
virtual const char *getScriptableName() const { return "UILabel"; }
private:
std::string m_text;
int m_align;
AlignmentFlag m_align;
Color m_color;
};

View File

@ -30,28 +30,18 @@
void UILabelSkin::load(const YAML::Node& node)
{
UIElementSkin::load(node);
if(node.FindValue("font"))
m_font = g_fonts.get(node["font"].Read<std::string>());
else
m_font = g_fonts.getDefaultFont();
if(node.FindValue("text color"))
node["text color"] >> m_textColor;
else
m_textColor = Color::white;
}
void UILabelSkin::apply(UIElement* element)
{
UIElementSkin::apply(element);
UILabel *label = static_cast<UILabel*>(element);
label->setSize(m_font->calculateTextRectSize(label->getText()));
label->setSize(getFont()->calculateTextRectSize(label->getText()));
}
void UILabelSkin::draw(UIElement *element)
{
UIElementSkin::draw(element);
UILabel *label = static_cast<UILabel*>(element);
m_font->renderText(label->getText(), label->getRect(), label->getAlign(), m_textColor);
getFont()->renderText(label->getText(), label->getRect(), label->getAlign(), getFontColor());
}

View File

@ -33,19 +33,11 @@ class UILabelSkin : public UIElementSkin
{
public:
UILabelSkin(const std::string& name) :
UIElementSkin(name, UI::Label),
m_align(ALIGN_TOP_LEFT) { }
UIElementSkin(name, UI::Label) { }
void load(const YAML::Node& node);
void apply(UIElement *element);
void draw(UIElement *element);
Font *getFont() const { return m_font; }
private:
Font *m_font;
int m_align;
Color m_textColor;
};
#endif // UILABELSKIN_H

View File

@ -96,7 +96,7 @@ UIElementPtr UILoader::loadFile(const std::string& file, const UIContainerPtr& p
// create element interpreting it's id
UIElementPtr element = createElementFromId(elementId);
if(!element)
throw YAML::Exception(doc.begin().first().GetMark(), "invalid element type");
yamlThrowError(doc.begin().first(), "invalid element type");
parent->addChild(element);
// populete it
@ -136,7 +136,7 @@ void UILoader::populateContainer(const UIContainerPtr& parent, const YAML::Node&
UIElementPtr element = createElementFromId(id);
if(!element) {
logError(YAML::Exception(cnode.GetMark(), "invalid element type").what());
logError(yamlErrorDesc(cnode, "invalid element type"));
continue;
}
parent->addChild(element);
@ -167,78 +167,59 @@ void UILoader::loadElements(const UIElementPtr& parent, const YAML::Node& node)
void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
{
// set element skin
if(node.FindValue("skin")) {
if(node["skin"].GetType() == YAML::CT_SCALAR) {
element->setSkin(g_uiSkins.getElementSkin(element->getElementType(), node["skin"]));
if(yamlHasValue(node, "skin")) {
const YAML::Node& cnode = node["skin"];
if(cnode.GetType() == YAML::CT_SCALAR) {
element->setSkin(g_uiSkins.getElementSkin(element->getElementType(), cnode));
} else {
UIElementSkinPtr skin = UIElementSkinPtr(new UIElementSkin());
skin->load(node["skin"]);
skin->load(cnode);
element->setSkin(skin);
}
} else // apply default skin
element->setSkin(g_uiSkins.getElementSkin(element->getElementType(), "default"));
// load elements common proprieties
if(node.FindValue("size")) {
Size size;
node["size"] >> size;
element->setSize(size);
}
if(yamlHasValue(node, "size"))
element->setSize(yamlRead<Size>(node, "size"));
element->setMarginLeft(yamlRead(node, "margin.left", 0));
element->setMarginRight(yamlRead(node, "margin.right", 0));
element->setMarginTop(yamlRead(node, "margin.top", 0));
element->setMarginBottom(yamlRead(node, "margin.bottom", 0));
int margin;
if(node.FindValue("margin.left")) {
node["margin.left"] >> margin;
element->setMarginLeft(margin);
}
if(node.FindValue("margin.right")) {
node["margin.right"] >> margin;
element->setMarginRight(margin);
}
if(node.FindValue("margin.top")) {
node["margin.top"] >> margin;
element->setMarginTop(margin);
}
if(node.FindValue("margin.bottom")) {
node["margin.bottom"] >> margin;
element->setMarginBottom(margin);
}
if(node.FindValue("anchors.left"))
if(yamlHasValue(node, "anchors.left"))
loadElementAnchor(element, UI::AnchorLeft, node["anchors.left"]);
if(node.FindValue("anchors.right"))
if(yamlHasValue(node, "anchors.right"))
loadElementAnchor(element, UI::AnchorRight, node["anchors.right"]);
if(node.FindValue("anchors.top"))
if(yamlHasValue(node, "anchors.top"))
loadElementAnchor(element, UI::AnchorTop, node["anchors.top"]);
if(node.FindValue("anchors.bottom"))
if(yamlHasValue(node, "anchors.bottom"))
loadElementAnchor(element, UI::AnchorBottom, node["anchors.bottom"]);
if(node.FindValue("anchors.horizontalCenter"))
if(yamlHasValue(node, "anchors.horizontalCenter"))
loadElementAnchor(element, UI::AnchorHorizontalCenter, node["anchors.horizontalCenter"]);
if(node.FindValue("anchors.verticalCenter"))
if(yamlHasValue(node, "anchors.verticalCenter"))
loadElementAnchor(element, UI::AnchorVerticalCenter, node["anchors.verticalCenter"]);
// load events
if(node.FindValue("onLoad")) {
if(yamlHasValue(node, "onLoad")) {
const YAML::Node& cnode = node["onLoad"];
if(g_lua.loadBufferAsFunction(cnode.Read<std::string>(), element->getId() + ":onLoad"))
if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), element->getId() + ":onLoad"))
g_lua.setScriptableField(element, "onLoad");
else
logError(YAML::Exception(cnode.GetMark(), "failed to parse inline lua script").what());
logError(yamlErrorDesc(cnode, "failed to parse inline lua script"));
}
if(node.FindValue("onDestroy")) {
if(yamlHasValue(node, "onDestroy")) {
const YAML::Node& cnode = node["onDestroy"];
if(g_lua.loadBufferAsFunction(cnode.Read<std::string>(), element->getId() + ":onDestroy"))
if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), element->getId() + ":onDestroy"))
g_lua.setScriptableField(element, "onDestroy");
else
logError(YAML::Exception(cnode.GetMark(), "failed to parse inline lua script").what());
logError(yamlErrorDesc(cnode, "failed to parse inline lua script"));
}
// load specific element type
@ -246,19 +227,12 @@ void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
loadButton(boost::static_pointer_cast<UIButton>(element), node);
else if(element->getElementType() == UI::Window) {
UIWindowPtr window = boost::static_pointer_cast<UIWindow>(element);
if(node.FindValue("title"))
window->setTitle(node["title"].Read<std::string>());
window->setTitle(yamlRead(node, "title", std::string()));
}
else if(element->getElementType() == UI::Label) {
UILabelPtr label = boost::static_pointer_cast<UILabel>(element);
if(node.FindValue("text"))
label->setText(node["text"].Read<std::string>());
if(node.FindValue("align")) {
std::string alignDesc;
node["align"] >> alignDesc;
if(alignDesc == "center")
label->setAlign(ALIGN_CENTER);
}
label->setText(yamlRead(node, "text", std::string()));
label->setAlign(parseAlignment(yamlRead(node, "align", std::string())));
}
}
@ -266,7 +240,7 @@ void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, UI::Anchor
{
UIAnchorLayoutPtr layout = boost::dynamic_pointer_cast<UIAnchorLayout>(anchoredElement->getLayout());
if(!layout) {
logError(YAML::Exception(node.GetMark(), "could not add anchor, because this element does not participate of an anchor layout").what());
logError(yamlErrorDesc(node, "could not add anchor, because this element does not participate of an anchor layout"));
return;
}
@ -276,7 +250,7 @@ void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, UI::Anchor
std::vector<std::string> split;
boost::split(split, anchorDescription, boost::is_any_of(std::string(".")));
if(split.size() != 2) {
logError(YAML::Exception(node.GetMark(), "invalid anchor").what());
logError(yamlErrorDesc(node, "invalid anchor"));
return;
}
@ -284,12 +258,12 @@ void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, UI::Anchor
UI::AnchorPoint anchorLineEdge = UIAnchorLayout::parseAnchorPoint(split[1]);
if(anchorLineEdge == UI::AnchorNone) {
logError(YAML::Exception(node.GetMark(), "invalid anchor type").what());
logError(yamlErrorDesc(node, "invalid anchor type"));
return;
}
if(!layout->addAnchor(anchoredElement, anchoredEdge, AnchorLine(anchorLineElementId, anchorLineEdge)))
logError(YAML::Exception(node.GetMark(), "anchoring failed").what());
logError(yamlErrorDesc(node, "anchoring failed"));
}
void UILoader::loadButton(const UIButtonPtr& button, const YAML::Node& node)
@ -297,10 +271,11 @@ void UILoader::loadButton(const UIButtonPtr& button, const YAML::Node& node)
button->setText(node["text"].Read<std::string>());
// set on click event
if(node.FindValue("onClick")) {
if(g_lua.loadBufferAsFunction(node["onClick"].Read<std::string>(), button->getId() + ":onClick"))
if(yamlHasValue(node, "onClick")) {
const YAML::Node& cnode = node["onClick"];
if(g_lua.loadBufferAsFunction(yamlRead<std::string>(cnode), button->getId() + ":onClick"))
g_lua.setScriptableField(button, "onClick");
else
logError(YAML::Exception(node["onClick"].GetMark(), "failed to parse inline lua script").what());
logError(yamlErrorDesc(cnode, "failed to parse inline lua script"));
}
}

View File

@ -31,6 +31,7 @@
#include <ui/uiwindowskin.h>
#include <ui/uitexteditskin.h>
#include <ui/uilabelskin.h>
#include <graphics/fonts.h>
UISkins g_uiSkins;
@ -48,9 +49,15 @@ void UISkins::load(const std::string& skinsFile)
YAML::Node doc;
parser.GetNextDocument(doc);
std::string defaultTexture;
doc["default skin image"] >> defaultTexture;
m_defaultTexture = g_textures.get("skins/" + defaultTexture);
m_defaultFont = g_fonts.get(yamlRead<std::string>(doc, "default font"));
if(!m_defaultFont)
logFatal("FATAL ERROR: Could not load skin default font");
m_defaultFontColor = yamlRead(doc, "default font color", Color::white);
std::string defaultTextureName = yamlRead(doc, "default texture", std::string());
if(!defaultTextureName.empty())
m_defaultTexture = g_textures.get("skins/" + defaultTextureName);
{
const YAML::Node& node = doc["buttons"];

View File

@ -28,6 +28,7 @@
#include <prerequisites.h>
#include <graphics/texture.h>
#include <ui/uielementskin.h>
#include <graphics/font.h>
class UISkins
{
@ -39,9 +40,13 @@ public:
UIElementSkinPtr getElementSkin(UI::ElementType elementType, const std::string& name = "default");
TexturePtr getDefaultTexture() { return m_defaultTexture; }
FontPtr getDefaultFont() { return m_defaultFont; }
Color getDefaultFontColor() { return m_defaultFontColor; }
private:
TexturePtr m_defaultTexture;
FontPtr m_defaultFont;
Color m_defaultFontColor;
std::vector<UIElementSkinPtr> m_elementSkins;
};

View File

@ -23,7 +23,6 @@
#include <prerequisites.h>
#include <graphics/fonts.h>
#include <ui/uitextedit.h>
#include <ui/uitexteditskin.h>
#include <ui/uicontainer.h>

View File

@ -30,28 +30,15 @@
void UITextEditSkin::load(const YAML::Node& node)
{
UIElementSkin::load(node);
if(node.FindValue("font")) {
m_font = g_fonts.get(node["font"].Read<std::string>());
} else
m_font = g_fonts.getDefaultFont();
if(node.FindValue("text color"))
node["text color"] >> m_textColor;
else
m_textColor = Color::white;
if(node.FindValue("text margin"))
node["text margin"] >> m_textMargin;
else
m_textMargin = 2;
m_textMargin = yamlRead(node, "text margin", 2);
}
void UITextEditSkin::apply(UIElement* element)
{
UIElementSkin::apply(element);
UITextEdit *textEdit = static_cast<UITextEdit*>(element);
textEdit->getTextArea().setFont(m_font);
textEdit->getTextArea().setFont(getFont());
textEdit->getTextArea().setColor(getFontColor());
}
void UITextEditSkin::draw(UIElement* element)

View File

@ -40,13 +40,10 @@ public:
void apply(UIElement *element);
void draw(UIElement *element);
Font *getFont() const { return m_font; }
int getTextMargin() const { return m_textMargin; }
private:
Font *m_font;
int m_textMargin;
Color m_textColor;
};
#endif // UITEXTEDITSKIN_H

View File

@ -30,34 +30,36 @@ void UIWindowSkin::load(const YAML::Node& node)
{
UIElementSkin::load(node);
node["head"]["height"] >> m_headHeight;
m_headImage = loadImage(node["head"]);
m_bodyImage = loadImage(node["body"]);
const YAML::Node& headNode = node["head"];
const YAML::Node& bodyNode = node["body"];
std::string fontName;
node["head"]["font"] >> fontName;
m_titleFont = g_fonts.get(fontName);
node["head"]["text color"] >> m_headTextColor;
m_headImage = boost::dynamic_pointer_cast<BorderedImage>(loadImage(headNode));
m_headHeight = yamlRead(headNode, "height", m_headImage->getDefaultSize().height());
m_headMargin = yamlRead(headNode, "margin", 0);
m_titleAlign = parseAlignment(yamlRead(headNode, "text align", std::string("center")));
m_bodyImage = loadImage(bodyNode);
}
void UIWindowSkin::draw(UIElement* element)
{
UIElementSkin::draw(element);
UIWindow *window = static_cast<UIWindow*>(element);
// draw window head
Rect headRect = window->getRect();
Rect bodyRect = window->getRect();
headRect.setHeight(m_headHeight);
bodyRect.setTop(headRect.bottom() + 1);
m_headImage->draw(headRect);
m_titleFont->renderText(window->getTitle(),
headRect,
ALIGN_CENTER,
m_headTextColor);
// draw window head text
Rect headTextRect = headRect;
if(m_titleAlign & AlignLeft)
headTextRect.addLeft(-m_headMargin);
else if(m_titleAlign & AlignRight)
headTextRect.addRight(-m_headMargin);
getFont()->renderText(window->getTitle(), headTextRect, m_titleAlign, getFontColor());
// draw window body
Rect bodyRect = window->getRect();
bodyRect.setTop(headRect.bottom() + 1);
m_bodyImage->draw(bodyRect);
}

View File

@ -27,6 +27,7 @@
#include <prerequisites.h>
#include <graphics/font.h>
#include <ui/uielementskin.h>
#include <graphics/borderedimage.h>
class UIWindowSkin : public UIElementSkin
{
@ -40,11 +41,12 @@ public:
int getHeadHeight() const { return m_headHeight; }
private:
ImagePtr m_headImage;
BorderedImagePtr m_headImage;
ImagePtr m_bodyImage;
Font *m_titleFont;
FontPtr m_titleFont;
int m_headHeight;
Color m_headTextColor;
int m_headMargin;
AlignmentFlag m_titleAlign;
};
#endif // UIWINDOWSKIN_H

View File

@ -67,16 +67,6 @@ private:
RGBA color;
};
inline void operator>>(const YAML::Node& node, Color& color)
{
int r, g, b, a;
node[0] >> r;
node[1] >> g;
node[2] >> b;
node[3] >> a;
color.setRGBA(r,g,b,a);
}
inline std::ostream& operator<<(std::ostream& out, const Color& color)
{
out << "Color(" << (int)color.r() << ","

View File

@ -77,13 +77,6 @@ public:
typedef TPoint<int> Point;
typedef TPoint<float> PointF;
template <class T>
inline void operator>>(const YAML::Node& node, TPoint<T>& point)
{
node[0] >> point.x;
node[1] >> point.y;
}
template <class T>
inline std::ostream& operator<<(std::ostream& out, const TPoint<T>& point)
{

View File

@ -299,17 +299,6 @@ private:
typedef TRect<int> Rect;
typedef TRect<float> RectF;
template <class T>
inline void operator>>(const YAML::Node& node, TRect<T>& rect)
{
T x, y, width, height;
node[0] >> x;
node[1] >> y;
node[2] >> width;
node[3] >> height;
rect.setRect(x, y, width, height);
}
template <class T>
inline std::ostream& operator<<(std::ostream& out, const TRect<T>& rect)
{

View File

@ -111,15 +111,6 @@ private:
typedef TSize<int> Size;
typedef TSize<float> SizeF;
template <class T>
inline void operator>>(const YAML::Node& node, TSize<T>& size)
{
T w, h;
node[0] >> w;
node[1] >> h;
size.setSize(w, h);
}
template <class T>
inline std::ostream& operator<<(std::ostream& out, const TSize<T>& size)
{

View File

@ -22,4 +22,28 @@
*/
#include <util/util.h>
#include <cstdio>
#include <boost/algorithm/string.hpp>
AlignmentFlag parseAlignment(std::string aligment)
{
boost::to_lower(aligment);
boost::erase_all(aligment, " ");
if(aligment == "topleft")
return AlignTopLeft;
else if(aligment == "topright")
return AlignTopRight;
else if(aligment == "bottomleft")
return AlignBottomLeft;
else if(aligment == "bottomright")
return AlignBottomRight;
else if(aligment == "left")
return AlignLeftCenter;
else if(aligment == "right")
return AlignRightCenter;
else if(aligment == "top")
return AlignTopCenter;
else if(aligment == "bottom")
return AlignBottomCenter;
else
return AlignCenter;
}

View File

@ -28,13 +28,14 @@
#include <util/logger.h>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <constants.h>
/// Easy/fast writting formater
#define f(a, b) (boost::format(a) % b).str()
// Easy/fast writing formater
#define fmt(a, b) (boost::format(a) % b).str()
/// Convert any data type through boost::lexical_cast
template<class R, class T>
R convertType(T t)
template<class R, class T>
R convert_cast(T t)
{
R ret = R();
try {
@ -45,4 +46,7 @@ R convertType(T t)
return ret;
}
AlignmentFlag parseAlignment(std::string aligment);
#endif // UTIL_H

122
src/framework/util/yaml.h Normal file
View File

@ -0,0 +1,122 @@
/* The MIT License
*
* Copyright (c) 2010 OTClient, https://github.com/edubart/otclient
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef YAML_H
#define YAML_H
#include <prerequisites.h>
#include <yaml-cpp/yaml.h>
inline void operator>>(const YAML::Node& node, Color& color)
{
int r, g, b, a;
node[0] >> r;
node[1] >> g;
node[2] >> b;
node[3] >> a;
color.setRGBA(r,g,b,a);
}
template <class T>
inline void operator>>(const YAML::Node& node, TPoint<T>& point)
{
node[0] >> point.x;
node[1] >> point.y;
}
template <class T>
inline void operator>>(const YAML::Node& node, TRect<T>& rect)
{
T x, y, width, height;
node[0] >> x;
node[1] >> y;
node[2] >> width;
node[3] >> height;
rect.setRect(x, y, width, height);
}
template <class T>
inline void operator>>(const YAML::Node& node, TSize<T>& size)
{
T w, h;
node[0] >> w;
node[1] >> h;
size.setSize(w, h);
}
template<class T>
inline T yamlRead(const YAML::Node& node)
{
return node.Read<T>();
}
template<class T>
inline T yamlRead(const YAML::Node& node, const char *name)
{
T value;
node[name] >> value;
return value;
}
template<class T>
inline T yamlRead(const YAML::Node& node, const char *name, const T& defaultValue)
{
T value = defaultValue;
if(node.FindValue(name))
node[name] >> value;
return value;
}
inline bool yamlHasValue(const YAML::Node& node, const char *name)
{
return node.FindValue(name) != NULL;
}
inline std::string yamlErrorDesc(const YAML::Node& node, const std::string& error)
{
return YAML::Exception(node.GetMark(), error.c_str()).what();
}
inline void yamlThrowError(const YAML::Node& node, const std::string& error)
{
throw YAML::Exception(node.GetMark(), error.c_str());
}
template<class A, class B>
inline std::map<A,B> yamlReadMap(const YAML::Node& node, const char *name)
{
std::map<A,B> map;
if(const YAML::Node* mapNode = node.FindValue(name)) {
for(auto it = mapNode->begin(); it != mapNode->end(); ++it) {
A a;
B b;
it.first() >> a;
it.second() >> b;
map[a] = b;
}
}
return map;
}
#endif // YAML_H

View File

@ -115,7 +115,7 @@ int main(int argc, const char *argv[])
g_engine.enableFpsCounter();
// load ui skins
g_uiSkins.load("skins/tibiaskin.yml");
g_uiSkins.load("skins/lightness.yml");
// load script modules
g_lua.loadAllModules();