loading ui from files
This commit is contained in:
parent
150afa86f3
commit
792d661dad
|
@ -55,6 +55,7 @@ SET(SOURCES
|
|||
# game sources
|
||||
src/main.cpp
|
||||
src/menustate.cpp
|
||||
src/mainmenu.cpp
|
||||
src/teststate.cpp
|
||||
|
||||
# game net
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#include "graphics.h"
|
||||
#include "textures.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
BorderedImage::BorderedImage(TexturePtr texture,
|
||||
const Rect& left,
|
||||
const Rect& right,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
|
||||
#include "anchorlayout.h"
|
||||
#include "uielement.h"
|
||||
|
||||
int AnchorLine::getPos() const
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -24,3 +24,8 @@
|
|||
|
||||
#include "uiwindow.h"
|
||||
|
||||
void UIWindow::load(const YAML::Node& node)
|
||||
{
|
||||
UIContainer::load(node);
|
||||
node["title"] >> m_title;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue