loading ui from files

This commit is contained in:
Eduardo Bart 2011-04-10 04:34:52 -03:00
parent 150afa86f3
commit 792d661dad
15 changed files with 276 additions and 12 deletions

View File

@ -55,6 +55,7 @@ SET(SOURCES
# game sources
src/main.cpp
src/menustate.cpp
src/mainmenu.cpp
src/teststate.cpp
# game net

View File

@ -26,8 +26,6 @@
#include "graphics.h"
#include "textures.h"
#include <GL/gl.h>
BorderedImage::BorderedImage(TexturePtr texture,
const Rect& left,
const Rect& right,

View File

@ -23,6 +23,7 @@
#include "anchorlayout.h"
#include "uielement.h"
int AnchorLine::getPos() const
{

View File

@ -97,6 +97,11 @@ public:
void setMargin(int horizontal, int vertical) { m_marginLeft = m_marginRight = horizontal; m_marginTop = m_marginBottom = vertical; recalculateAnchors(); }
void setMargin(int margin) { m_marginLeft = m_marginRight = m_marginTop = m_marginBottom = margin; recalculateAnchors(); }
void setMarginLeft(int margin) { m_marginLeft = margin; recalculateAnchors(); }
void setMarginRight(int margin) { m_marginRight = margin; recalculateAnchors(); }
void setMarginTop(int margin) { m_marginTop = margin; recalculateAnchors(); }
void setMarginBottom(int margin) { m_marginBottom = margin; recalculateAnchors(); }
AnchorLayoutPtr asAnchorLayout() { return shared_from_this(); }
private:

View File

@ -26,6 +26,12 @@
#include "../fonts.h"
#include "../font.h"
void UIButton::load(const YAML::Node& node)
{
UIElement::load(node);
node["text"] >> m_text;
}
void UIButton::render()
{
UIElement::render();

View File

@ -34,12 +34,14 @@ typedef std::function<void()> Callback;
class UIButton : public UIElement
{
public:
UIButton(const std::string& text) : UIElement(UI::Button),
UIButton(const std::string& text = std::string()) : UIElement(UI::Button),
m_text(text),
m_state(UI::ButtonUp) {
UIElement();
}
void load(const YAML::Node& node);
virtual void render();
bool onInputEvent(const InputEvent& event);

View File

@ -23,9 +23,99 @@
#include "uicontainer.h"
#include "../resources.h"
#include "uibutton.h"
#include "uipanel.h"
#include "uilabel.h"
#include "uitextedit.h"
#include "uiwindow.h"
UIContainerPtr g_ui(new UIContainer);
UIElementPtr createElementFromDescription(std::string elementId)
{
UIElementPtr element;
std::vector<std::string> split;
boost::split(split, elementId, boost::is_any_of("-"));
if(split.size() != 2) {
logError("incorrect element id format: %s", elementId.c_str());
return element;
}
std::string elementType = split[1];
if(elementType == "panel") {
element = UIElementPtr(new UIPanel);
} else if(elementType == "button") {
element = UIElementPtr(new UIButton);
} else if(elementType == "label") {
element = UIElementPtr(new UILabel);
} else if(elementType == "window") {
element = UIElementPtr(new UIWindow);
} else if(elementType == "textEdit") {
element = UIElementPtr(new UITextEdit);
}
if(element)
element->setId(elementId);
return element;
}
void UIContainer::load(const YAML::Node& node)
{
UIElement::load(node);
for(auto it = node.begin(); it != node.end(); ++it) {
std::string elementDesc;
it.first() >> elementDesc;
if(elementDesc.find("-") != std::string::npos) {
UIElementPtr element = createElementFromDescription(elementDesc);
if(element) {
addChild(element);
element->load(it.second());
}
}
}
}
UIContainerPtr UIContainer::load(const std::string& file)
{
//TODO: handle errors
//TODO: display errors in which file and line
UIContainerPtr container;
std::string fileContents = g_resources.loadTextFile(file);
if(!fileContents.size()) {
logFatal("could not load ui file \"%s", file.c_str());
return UIContainerPtr();
}
std::istringstream fin(fileContents);
try {
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc);
std::string elementDesc;
doc.begin().first() >> elementDesc;
UIElementPtr element = createElementFromDescription(elementDesc);
if(element) {
g_ui->addChild(element);
element->load(doc.begin().second());
return element->asUIContainer();
}
} catch (YAML::ParserException& e) {
logError("Malformed ui file \"%s\": %s", file.c_str(), e.what());
return UIContainerPtr();
}
return container;
}
void UIContainer::addChild(UIElementPtr child)
{
m_children.push_back(child);
@ -41,12 +131,35 @@ void UIContainer::removeChild(UIElementPtr child)
child->setParent(UIContainerPtr());
}
UIElementPtr UIContainer::getChildById(const std::string& id) const
UIElementPtr UIContainer::getChildById(const std::string& id)
{
if(getId() == id)
return asUIElement();
for(auto it = m_children.begin(); it != m_children.end(); ++it) {
if((*it)->getId() == id) {
return (*it);
break;
}
}
return UIElementPtr();
}
UIElementPtr UIContainer::recursiveGetChildById(const std::string& id)
{
if(getId() == id)
return asUIElement();
UIElementPtr element;
for(auto it = m_children.begin(); it != m_children.end(); ++it) {
element = (*it);
if(element->getId() == id) {
return element;
} else {
UIContainerPtr container = element->asUIContainer();
if(container) {
element = container->recursiveGetChildById(id);
if(element)
return element;
}
}
}
return UIElementPtr();

View File

@ -25,6 +25,7 @@
#ifndef UICONTAINER_H
#define UICONTAINER_H
//TODO: make includes paths, so this will be cleaner
#include "../prerequisites.h"
#include "uielement.h"
#include "../point.h"
@ -36,9 +37,17 @@ public:
UIContainer(UI::EElementType type = UI::Container) : UIElement(type) { }
virtual ~UIContainer() { }
virtual void load(const YAML::Node& node);
//TODO: move this shit
static UIContainerPtr load(const std::string& file);
void addChild(UIElementPtr child);
void removeChild(UIElementPtr child);
UIElementPtr getChildById(const std::string& id) const;
UIElementPtr getChildById(const std::string& id);
//TODO: make this backwards
UIElementPtr recursiveGetChildById(const std::string& id);
virtual void render();
virtual bool onInputEvent(const InputEvent& event);
@ -53,9 +62,6 @@ public:
protected:
std::list<UIElementPtr> m_children;
UIElementPtr m_activeElement;
private:
void onMove(const Point& pos);
};
extern UIContainerPtr g_ui;

View File

@ -38,6 +38,106 @@ UIElement::UIElement(UI::EElementType type) :
setSkin(g_uiSkins.getElementSkin(type));
}
void UIElement::load(const YAML::Node& node)
{
if(node.FindValue("skin"))
setSkin(g_uiSkins.getElementSkin(m_type, node["skin"]));
if(node.FindValue("size")) {
Size size;
node["size"] >> size;
setSize(size);
}
int margin;
if(node.FindValue("margin.left")) {
node["margin.left"] >> margin;
setMarginLeft(margin);
}
if(node.FindValue("margin.right")) {
node["margin.right"] >> margin;
setMarginRight(margin);
}
if(node.FindValue("margin.top")) {
node["margin.top"] >> margin;
setMarginTop(margin);
}
if(node.FindValue("margin.bottom")) {
node["margin.bottom"] >> margin;
setMarginBottom(margin);
}
if(node.FindValue("anchors.left"))
loadAnchor(ANCHOR_LEFT, node["anchors.left"]);
if(node.FindValue("anchors.right"))
loadAnchor(ANCHOR_RIGHT, node["anchors.right"]);
if(node.FindValue("anchors.top"))
loadAnchor(ANCHOR_TOP, node["anchors.top"]);
if(node.FindValue("anchors.bottom"))
loadAnchor(ANCHOR_BOTTOM, node["anchors.bottom"]);
if(node.FindValue("anchors.horizontalCenter"))
loadAnchor(ANCHOR_HORIZONTAL_CENTER, node["anchors.horizontalCenter"]);
if(node.FindValue("anchors.verticalCenter"))
loadAnchor(ANCHOR_VERTICAL_CENTER, node["anchors.verticalCenter"]);
}
void UIElement::loadAnchor(EAnchorType type, const YAML::Node& node)
{
std::string anchorDescription;
node >> anchorDescription;
std::vector<std::string> split;
boost::split(split, anchorDescription, boost::is_any_of("."));
if(split.size() != 2) {
logError("wrong anchors description: %s", anchorDescription.c_str());
return;
}
std::string relativeElementId = split[0];
std::string relativeAnchorTypeId = split[1];
EAnchorType relativeAnchorType;
if(relativeAnchorTypeId == "left")
relativeAnchorType = ANCHOR_LEFT;
else if(relativeAnchorTypeId == "right")
relativeAnchorType = ANCHOR_RIGHT;
else if(relativeAnchorTypeId == "top")
relativeAnchorType = ANCHOR_TOP;
else if(relativeAnchorTypeId == "bottom")
relativeAnchorType = ANCHOR_BOTTOM;
else if(relativeAnchorTypeId == "horizontalCenter")
relativeAnchorType = ANCHOR_HORIZONTAL_CENTER;
else if(relativeAnchorTypeId == "verticalCenter")
relativeAnchorType = ANCHOR_VERTICAL_CENTER;
else {
logError("wrong anchors description: %s", anchorDescription.c_str());
return;
}
AnchorLayoutPtr relativeElement;
if(relativeElementId == "parent" && getParent()) {
relativeElement = getParent()->asAnchorLayout();
} else {
UIElementPtr element = g_ui->recursiveGetChildById(relativeElementId);
if(element)
relativeElement = element->asAnchorLayout();
}
if(relativeElement) {
addAnchor(type, AnchorLine(relativeElement, relativeAnchorType));
} else {
logError("anchoring has failed: %s", anchorDescription.c_str());
return;
}
}
bool UIElement::setSkin(const std::string& skinName)
{

View File

@ -50,6 +50,9 @@ public:
virtual void render();
virtual bool onInputEvent(const InputEvent& event) { return false; }
virtual void load(const YAML::Node& node);
void loadAnchor(EAnchorType type, const YAML::Node& node);
bool setSkin(const std::string& skinName);
void setSkin(UIElementSkin *skin);
UIElementSkin *getSkin() { return m_skin; }
@ -69,6 +72,7 @@ public:
UI::EElementType getElementType() const { return m_type; }
UIElementPtr asUIElement() { return std::static_pointer_cast<UIElement>(shared_from_this()); }
virtual UIContainerPtr asUIContainer() { return UIContainerPtr(); }
private:
UI::EElementType m_type;

View File

@ -35,6 +35,15 @@ UILabel::UILabel(const std::string& text, Font* font) :
setSize(m_font->calculateTextRectSize(text));
}
void UILabel::load(const YAML::Node& node)
{
UIElement::load(node);
std::string text;
node["text"] >> text;
setText(text);
}
void UILabel::render()
{
m_font->renderText(m_text, getRect(), ALIGN_LEFT, Color(0xFFBFBFBF));

View File

@ -33,7 +33,9 @@ class Font;
class UILabel : public UIElement
{
public:
UILabel(const std::string& text, Font *font = NULL);
UILabel(const std::string& text = std::string(), Font *font = NULL);
void load(const YAML::Node& node);
void render();

View File

@ -24,3 +24,8 @@
#include "uiwindow.h"
void UIWindow::load(const YAML::Node& node)
{
UIContainer::load(node);
node["title"] >> m_title;
}

View File

@ -31,10 +31,12 @@
class UIWindow : public UIContainer
{
public:
UIWindow(const std::string& title) :
UIWindow(const std::string& title = std::string()) :
UIContainer(UI::Window),
m_title(title) { }
void load(const YAML::Node& node);
const std::string& getTitle() const { return m_title; }
private:

View File

@ -42,7 +42,15 @@ void MenuState::onEnter()
m_background = g_textures.get("background.png");
m_background->enableBilinearFilter();
createMainMenu();
UIContainerPtr mainMenuPanel = UIContainer::load("ui/mainMenu-panel.yml");
UIButtonPtr button = std::static_pointer_cast<UIButton>(mainMenuPanel->getChildById("exitGame-button"));
button->onClick([]{ g_engine.stop(); });
button = std::static_pointer_cast<UIButton>(mainMenuPanel->getChildById("enterGame-button"));
button->onClick([]{
UIContainer::load("ui/enterGame-window.yml");
});
}
void MenuState::onLeave()
@ -82,6 +90,7 @@ void MenuState::render()
void MenuState::createMainMenu()
{
/*
int y = 0;
m_menuPanel = UIPanelPtr(new UIPanel);
@ -199,4 +208,5 @@ void MenuState::createMainMenu()
if(window)
window->setVisible(true);
});
*/
}