refator some stuff, button implementation

This commit is contained in:
Eduardo Bart 2011-04-09 16:07:35 -03:00
parent a5cd0bed74
commit 22c4b0976a
20 changed files with 91 additions and 224 deletions

View File

@ -73,8 +73,10 @@ SET(SOURCES
src/framework/util.cpp
# ui
src/framework/ui/anchorlayout.cpp
src/framework/ui/uielement.cpp
src/framework/ui/uielementskin.cpp
src/framework/ui/uibuttonskin.cpp
src/framework/ui/uicontainer.cpp
src/framework/ui/uiskins.cpp
src/framework/ui/uipanel.cpp

View File

@ -140,7 +140,7 @@ void Engine::onResize(const Size& size)
m_currentState->onResize(size);
}
void Engine::onInputEvent(InputEvent *event)
void Engine::onInputEvent(const InputEvent& event)
{
// inputs goest to gui first
if(!g_ui->onInputEvent(event)) {

View File

@ -60,7 +60,7 @@ public:
/// Fired by platform on window resize
void onResize(const Size& size);
/// Fired by platform on mouse/keyboard input
void onInputEvent(InputEvent *event);
void onInputEvent(const InputEvent& event);
/// Enable FPS counter on screen
void enableFpsCounter(bool enable = true) { m_calculateFps = enable; };

View File

@ -25,6 +25,7 @@
#ifndef GAMESTATE_H
#define GAMESTATE_H
#include "input.h"
#include "size.h"
struct InputEvent;
@ -39,7 +40,7 @@ public:
virtual void onLeave() = 0;
virtual void onClose() = 0;
virtual void onInputEvent(InputEvent *event) = 0;
virtual void onInputEvent(const InputEvent& event) = 0;
virtual void onResize(const Size& size) = 0;
virtual void render() = 0;

View File

@ -25,6 +25,8 @@
#ifndef INPUT_H
#define INPUT_H
#include "prerequisites.h"
enum EKeyCode {
KC_UNKNOWN = 0x00,
KC_ESCAPE = 0x01,

View File

@ -30,5 +30,17 @@ void UIButton::render()
{
UIElement::render();
g_fonts.get("tibia-8px-antialised")->renderText(m_text, m_rect, ALIGN_CENTER);
g_fonts.get("tibia-8px-antialised")->renderText(m_text, getRect(), ALIGN_CENTER);
}
bool UIButton::onInputEvent(const InputEvent& event)
{
if(event.type == EV_MOUSE_LDOWN &&
getRect().contains(Point(event.mouse.x, event.mouse.y))) {
m_state = UI::ButtonDown;
} else if(m_state == UI::ButtonDown &&
event.type == EV_MOUSE_LUP) {
m_state = UI::ButtonUp;
}
return false;
}

View File

@ -39,6 +39,9 @@ public:
}
virtual void render();
bool onInputEvent(const InputEvent& event);
UI::EButtonState getState() { return m_state; }
private:
std::string m_text;

View File

@ -53,7 +53,7 @@ namespace UI {
enum EElementType
{
Element,
Element = 0,
Container,
Panel,
Window,

View File

@ -57,13 +57,20 @@ void UIContainer::render()
UIElement::render();
for(auto it = m_children.begin(); it != m_children.end(); ++it) {
const UIElementPtr& child = (*it);
if(child->isVisible())
child->render();
}
}
bool UIContainer::onInputEvent(InputEvent* event)
bool UIContainer::onInputEvent(const InputEvent& event)
{
return false;
bool ret = false;
for(auto it = m_children.begin(); it != m_children.end(); ++it) {
const UIElementPtr& child = (*it);
if(child->isEnabled() && child->isVisible())
ret = child->onInputEvent(event) || ret;
}
return ret;
}
void UIContainer::setActiveElement(UIElementPtr activeElement)

View File

@ -41,7 +41,7 @@ public:
UIElementPtr getChildById(const std::string& id) const;
virtual void render();
virtual bool onInputEvent(InputEvent *event);
virtual bool onInputEvent(const InputEvent& event);
void setActiveElement(UIElementPtr activeElement);
UIElementPtr getActiveElement() const { return m_activeElement; }

View File

@ -26,39 +26,14 @@
#include "uiskins.h"
#include "uielementskin.h"
int AnchorLine::getPos() const
{
UIElementPtr element = m_relativeElement.lock();
if(element) {
switch(m_anchorType) {
case ANCHOR_LEFT:
return element->getRect().left();
case ANCHOR_RIGHT:
return element->getRect().right();
case ANCHOR_TOP:
return element->getRect().top();
case ANCHOR_BOTTOM:
return element->getRect().bottom();
case ANCHOR_HORIZONTAL_CENTER:
return element->getRect().horizontalCenter();
case ANCHOR_VERTICAL_CENTER:
return element->getRect().verticalCenter();
default:
return 0;
}
}
logError("anchor line of an element have expired");
return 0;
}
UIElement::UIElement(UI::EElementType type) :
AnchorLayout(),
m_type(type),
m_marginLeft(0),
m_marginRight(0),
m_marginTop(0),
m_marginBottom(0)
m_visible(true),
m_enabled(true)
{
// set default skin
if(type > UI::Container)
setSkin(g_uiSkins.getElementSkin(type));
}
@ -71,7 +46,7 @@ bool UIElement::setSkin(const std::string& skinName)
void UIElement::setSkin(UIElementSkin* skin)
{
if(skin && !m_rect.isValid()) {
if(skin && !getRect().isValid()) {
setSize(skin->getDefaultSize());
}
m_skin = skin;
@ -82,76 +57,3 @@ void UIElement::render()
if(m_skin)
m_skin->draw(this);
}
void UIElement::setSize(const Size& size)
{
m_rect.setSize(size);
recalculateAnchors();
}
void UIElement::setRect(const Rect& rect)
{
m_rect = rect;
recalculateAnchors();
}
void UIElement::addAnchor(EAnchorType type, const AnchorLine& anchorLine)
{
if(!anchorLine.isValid()) {
logError("anchoring for an element has failed, got an invalid anchor line");
return;
}
m_anchors[type] = anchorLine;
anchorLine.getRelativeElement()->addAnchoredElement(asUIElement());
recalculateAnchors();
}
void UIElement::addAnchoredElement(UIElementPtr anchoredElement)
{
bool found = false;
for(auto it = m_anchoredElements.begin(); it != m_anchoredElements.end(); ++it) {
if((*it).lock() == anchoredElement) {
found = true;
break;
}
}
if(!found)
m_anchoredElements.push_back(anchoredElement);
}
void UIElement::recalculateAnchors()
{
// horizontal
if(m_anchors[ANCHOR_HORIZONTAL_CENTER].isValid()) {
m_rect.moveHorizontalCenter(m_anchors[ANCHOR_HORIZONTAL_CENTER].getPos() + m_marginLeft - m_marginRight);
} else {
if(m_anchors[ANCHOR_LEFT].isValid() && m_anchors[ANCHOR_RIGHT].isValid()) {
m_rect.setLeft(m_anchors[ANCHOR_LEFT].getPos() + m_marginLeft);
m_rect.setRight(m_anchors[ANCHOR_RIGHT].getPos() - m_marginRight);
} else if(m_anchors[ANCHOR_LEFT].isValid()) {
m_rect.moveLeft(m_anchors[ANCHOR_LEFT].getPos() + m_marginLeft);
} else if(m_anchors[ANCHOR_RIGHT].isValid()) {
m_rect.moveRight(m_anchors[ANCHOR_RIGHT].getPos() - m_marginRight);
}
}
// vertical
if(m_anchors[ANCHOR_VERTICAL_CENTER].isValid()) {
m_rect.moveVerticalCenter(m_anchors[ANCHOR_VERTICAL_CENTER].getPos() + m_marginTop - m_marginBottom);
} else {
if(m_anchors[ANCHOR_TOP].isValid() && m_anchors[ANCHOR_BOTTOM].isValid()) {
m_rect.setLeft(m_anchors[ANCHOR_TOP].getPos() + m_marginTop);
m_rect.setRight(m_anchors[ANCHOR_BOTTOM].getPos() - m_marginBottom);
} else if(m_anchors[ANCHOR_TOP].isValid()) {
m_rect.moveTop(m_anchors[ANCHOR_TOP].getPos() + m_marginTop);
} else if(m_anchors[ANCHOR_BOTTOM].isValid()) {
m_rect.moveBottom(m_anchors[ANCHOR_BOTTOM].getPos() - m_marginBottom);
}
}
for(auto it = m_anchoredElements.begin(); it != m_anchoredElements.end(); ++it) {
UIElementPtr element = (*it).lock();
if(element)
element->recalculateAnchors();
}
}

View File

@ -29,6 +29,7 @@
#include "../input.h"
#include "../rect.h"
#include "uiconstants.h"
#include "anchorlayout.h"
class UIElementSkin;
@ -40,43 +41,14 @@ class UIElement;
typedef std::shared_ptr<UIElement> UIElementPtr;
typedef std::weak_ptr<UIElement> UIElementWeakPtr;
enum EAnchorType {
ANCHOR_LEFT = 0,
ANCHOR_RIGHT,
ANCHOR_TOP,
ANCHOR_BOTTOM,
ANCHOR_HORIZONTAL_CENTER,
ANCHOR_VERTICAL_CENTER,
ANCHOR_NONE
};
class AnchorLine
{
public:
AnchorLine() : m_anchorType(ANCHOR_NONE) { }
AnchorLine(const AnchorLine& other) :
m_relativeElement(other.m_relativeElement), m_anchorType(other.m_anchorType) { }
AnchorLine(UIElementPtr relativeElement, EAnchorType anchorType) :
m_relativeElement(relativeElement), m_anchorType(anchorType) { }
bool isValid() const { return (m_anchorType != ANCHOR_NONE && !m_relativeElement.expired()); }
int getPos() const;
EAnchorType getAnchorType() const { return m_anchorType; }
UIElementPtr getRelativeElement() const { return m_relativeElement.lock(); }
private:
UIElementWeakPtr m_relativeElement;
EAnchorType m_anchorType;
};
class UIElement : public std::enable_shared_from_this<UIElement>
class UIElement : public AnchorLayout
{
public:
UIElement(UI::EElementType type = UI::Element);
virtual ~UIElement() { }
virtual void render();
virtual bool onInputEvent(InputEvent *event) { return false; }
virtual bool onInputEvent(const InputEvent& event) { return false; }
bool setSkin(const std::string& skinName);
void setSkin(UIElementSkin *skin);
@ -88,62 +60,23 @@ public:
void setId(const std::string& id) { m_id = id; }
const std::string& getId() const { return m_id; }
void setSize(const Size& size);
Size getSize() { return m_rect.size(); }
void setRect(const Rect& rect);
const Rect& getRect() const{ return m_rect; }
void setActive(bool active) { m_active = active; }
bool isActive() const { return m_active; }
void setEnabled(bool enabled) { m_enabled = enabled; }
bool isEnabled() const { return m_enabled; }
void setVisible(bool visible) { m_visible = visible; }
bool isVisible() const { return m_visible; }
UI::EElementType getElementType() const { return m_type; }
UIElementPtr asUIElement() { return shared_from_this(); }
void recalculateAnchors();
void addAnchor(EAnchorType type, const AnchorLine& anchorLine);
void anchorLeft(const AnchorLine& anchorLine) { addAnchor(ANCHOR_LEFT, anchorLine); }
void anchorRight(const AnchorLine& anchorLine) { addAnchor(ANCHOR_RIGHT, anchorLine); }
void anchorTop(const AnchorLine& anchorLine) { addAnchor(ANCHOR_TOP, anchorLine); }
void anchorBottom(const AnchorLine& anchorLine) { addAnchor(ANCHOR_BOTTOM, anchorLine); }
void anchorHorizontalCenter(const AnchorLine& anchorLine) { addAnchor(ANCHOR_HORIZONTAL_CENTER, anchorLine); }
void anchorVerticalCenter(const AnchorLine& anchorLine) { addAnchor(ANCHOR_VERTICAL_CENTER, anchorLine); }
AnchorLine left() { return AnchorLine(asUIElement(), ANCHOR_LEFT); }
AnchorLine right() { return AnchorLine(asUIElement(), ANCHOR_RIGHT); }
AnchorLine top() { return AnchorLine(asUIElement(), ANCHOR_TOP); }
AnchorLine bottom() { return AnchorLine(asUIElement(), ANCHOR_BOTTOM); }
AnchorLine horizontalCenter() { return AnchorLine(asUIElement(), ANCHOR_HORIZONTAL_CENTER); }
AnchorLine verticalCenter() { return AnchorLine(asUIElement(), ANCHOR_VERTICAL_CENTER); }
void setMargin(int top, int left, int bottom, int right) { m_marginLeft = left; m_marginRight = right; m_marginTop = top; m_marginBottom = bottom; recalculateAnchors(); }
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(); }
protected:
void addAnchoredElement(UIElementPtr anchoredElement);
UIElementPtr asUIElement() { return std::static_pointer_cast<UIElement>(shared_from_this()); }
private:
UI::EElementType m_type;
UIContainerWeakPtr m_parent;
UIElementSkin *m_skin;
Rect m_rect;
std::string m_id;
bool m_visible;
bool m_active;
private:
AnchorLine m_anchors[6];
int m_marginLeft;
int m_marginRight;
int m_marginTop;
int m_marginBottom;
std::list<UIElementWeakPtr> m_anchoredElements;
bool m_enabled;
};
#endif // UIELEMENT_H

View File

@ -30,17 +30,20 @@
void UIElementSkin::draw(UIElement *element)
{
const ImagePtr& image = m_stateImages.front();
if(image) {
image->draw(element->getRect());
}
if(m_defaultImage)
m_defaultImage->draw(element->getRect());
}
void UIElementSkin::load(const YAML::Node& node)
{
if(node.FindValue("default size"))
node["default size"] >> m_defaultSize;
m_defaultImage = loadImage(node);
}
ImagePtr UIElementSkin::loadImage(const YAML::Node& node)
{
ImagePtr image;
if(node.FindValue("bordered image")) {
const YAML::Node& child = node["bordered image"];
Rect left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight, center;
@ -63,7 +66,7 @@ void UIElementSkin::load(const YAML::Node& node)
texture = g_uiSkins.getDefaultTexture();
}
ImagePtr image = ImagePtr(new BorderedImage(texture,
image = ImagePtr(new BorderedImage(texture,
left,
right,
top,
@ -73,6 +76,7 @@ void UIElementSkin::load(const YAML::Node& node)
bottomLeft,
bottomRight,
center));
m_stateImages.push_back(image);
}
return image;
}

View File

@ -39,18 +39,22 @@ public:
m_name(name),
m_elementType(elementType) { }
void load(const YAML::Node& node);
void draw(UIElement *element);
virtual void load(const YAML::Node& node);
virtual void draw(UIElement *element);
const std::string& getName() const { return m_name; }
const Size& getDefaultSize() const { return m_defaultSize; }
UI::EElementType getElementType() const { return m_elementType; }
ImagePtr getDefaultImage() const { return m_defaultImage; }
protected:
ImagePtr loadImage(const YAML::Node& node);
private:
std::string m_name;
UI::EElementType m_elementType;
Size m_defaultSize;
std::vector<ImagePtr> m_stateImages;
ImagePtr m_defaultImage;
};
#endif // UIELEMENTSKIN_H

View File

@ -26,6 +26,7 @@
#include "../resources.h"
#include "../textures.h"
#include "uielementskin.h"
#include "uibuttonskin.h"
UISkins g_uiSkins;
@ -61,9 +62,9 @@ bool UISkins::load(const std::string& file)
std::string name;
it.first() >> name;
UIElementSkin *elementSkin = new UIElementSkin(name, UI::Button);
elementSkin->load(it.second());
m_elementSkins.push_back(elementSkin);
UIButtonSkin *skin = new UIButtonSkin(name, UI::Button);
skin->load(it.second());
m_elementSkins.push_back(skin);
}
}
@ -73,9 +74,9 @@ bool UISkins::load(const std::string& file)
std::string name;
it.first() >> name;
UIElementSkin *elementSkin = new UIElementSkin(name, UI::Panel);
elementSkin->load(it.second());
m_elementSkins.push_back(elementSkin);
UIElementSkin *skin = new UIElementSkin(name, UI::Panel);
skin->load(it.second());
m_elementSkins.push_back(skin);
}
}
} catch (YAML::ParserException& e) {

View File

@ -351,7 +351,7 @@ void Platform::poll()
inputEvent.type = EV_TEXT_ENTER;
inputEvent.key.keychar = buf[0];
inputEvent.key.keycode = KC_UNKNOWN;
g_engine.onInputEvent(&inputEvent);
g_engine.onInputEvent(inputEvent);
}
}
@ -364,7 +364,7 @@ void Platform::poll()
inputEvent.key.keycode = x11.keyMap[keysym];
inputEvent.type = (event.type == KeyPress) ? EV_KEY_DOWN : EV_KEY_UP;
inputEvent.key.keychar = (len > 0) ? buf[0] : 0;
g_engine.onInputEvent(&inputEvent);
g_engine.onInputEvent(inputEvent);
}
break;
}
@ -387,14 +387,14 @@ void Platform::poll()
inputEvent.type = EV_MOUSE_WHEEL_DOWN;
break;
}
g_engine.onInputEvent(&inputEvent);
g_engine.onInputEvent(inputEvent);
break;
case MotionNotify:
inputEvent.type = EV_MOUSE_MOVE;
inputEvent.mouse.x = event.xbutton.x;
inputEvent.mouse.y = event.xbutton.y;
g_engine.onInputEvent(&inputEvent);
g_engine.onInputEvent(inputEvent);
break;
case MapNotify:

View File

@ -55,7 +55,7 @@ void MenuState::onClose()
g_engine.stop();
}
void MenuState::onInputEvent(InputEvent* event)
void MenuState::onInputEvent(const InputEvent& event)
{
}
@ -93,28 +93,24 @@ void MenuState::createMainMenu()
m_menuPanel->setMargin(0, 60, 70, 0);
button = UIButtonPtr(new UIButton("Enter Game"));
button->anchorLeft(m_menuPanel->left());
button->anchorTop(m_menuPanel->top());
button->anchorHorizontalCenter(m_menuPanel->horizontalCenter());
button->setMargin(y += 16);
m_menuPanel->addChild(button);
button = UIButtonPtr(new UIButton("Access Account"));
button->anchorLeft(m_menuPanel->left());
button->anchorTop(m_menuPanel->top());
button->anchorHorizontalCenter(m_menuPanel->horizontalCenter());
button->setMargin(y += 30);
m_menuPanel->addChild(button);
button = UIButtonPtr(new UIButton("Options"));
button->anchorLeft(m_menuPanel->left());
button->anchorTop(m_menuPanel->top());
button->anchorHorizontalCenter(m_menuPanel->horizontalCenter());
button->setMargin(y += 30);
m_menuPanel->addChild(button);
button = UIButtonPtr(new UIButton("Info"));
button->anchorLeft(m_menuPanel->left());
button->anchorTop(m_menuPanel->top());
button->anchorHorizontalCenter(m_menuPanel->horizontalCenter());
button->setMargin(y += 30);

View File

@ -40,7 +40,7 @@ public:
void onLeave();
void onClose();
void onInputEvent(InputEvent *event);
void onInputEvent(const InputEvent& event);
void onResize(const Size& size);
void render();

View File

@ -43,7 +43,7 @@ void TestState::onClose()
g_engine.stop();
}
void TestState::onInputEvent(InputEvent* event)
void TestState::onInputEvent(const InputEvent& event)
{
}

View File

@ -36,7 +36,7 @@ public:
void onLeave();
void onClose();
void onInputEvent(InputEvent *event);
void onInputEvent(const InputEvent& event);
void onResize(const Size& size);
void render();