ui skinning

This commit is contained in:
Eduardo Bart 2011-04-08 20:20:44 -03:00
parent f54ef6401d
commit e94024de67
20 changed files with 347 additions and 76 deletions

View File

@ -74,7 +74,9 @@ SET(SOURCES
# ui
src/framework/ui/uielement.cpp
src/framework/ui/uielementskin.cpp
src/framework/ui/uicontainer.cpp
src/framework/ui/uiskins.cpp
src/framework/ui/uipanel.cpp
src/framework/ui/uibutton.cpp
src/framework/ui/uilabel.cpp

View File

@ -136,7 +136,7 @@ void Engine::render()
g_graphics.beginRender();
if(m_currentState)
m_currentState->render();
g_gui->render();
g_ui->render();
g_graphics.endRender();
}
@ -144,7 +144,7 @@ void Engine::update(int ticks, int elapsedTicks)
{
if(m_currentState)
m_currentState->update(ticks, elapsedTicks);
g_gui->update(ticks, elapsedTicks);
g_ui->update(ticks, elapsedTicks);
}
void Engine::onClose()
@ -156,7 +156,7 @@ void Engine::onClose()
void Engine::onResize(const Size& size)
{
g_graphics.resize(size);
g_gui->resize(size);
g_ui->resize(size);
if(m_currentState)
m_currentState->onResize(size);
@ -165,7 +165,7 @@ void Engine::onResize(const Size& size)
void Engine::onInputEvent(InputEvent *event)
{
// inputs goest to gui first
if(!g_gui->onInputEvent(event)) {
if(!g_ui->onInputEvent(event)) {
// if gui didnt capture the input then goes to the state
if(m_currentState)
m_currentState->onInputEvent(event);

View File

@ -36,11 +36,6 @@ Font::Font() :
bool Font::load(const std::string& file)
{
if(!g_resources.fileExists(file)) {
logError("Font file %s does not exists", file.c_str());
return false;
}
std::string fileContents = g_resources.loadTextFile(file);
if(!fileContents.size()) {
logError("Empty font file \"%s", file.c_str());

View File

@ -29,9 +29,11 @@
#include "uiconstants.h"
#include "uielement.h"
#include "uielementskin.h"
#include "uicontainer.h"
#include "uipanel.h"
#include "uibutton.h"
#include "uilabel.h"
#include "uiskins.h"
#endif // UI_H

View File

@ -26,25 +26,9 @@
#include "../fonts.h"
#include "../font.h"
UIButton::UIButton(const std::string& text) :
m_text(text),
m_state(UI::ButtonUp)
{
m_imageButtonUp = ImagePtr(new BorderedImage("ui.png",
Rect(45,139,1,18),
Rect(130,139,1,18),
Rect(46,138,84,1),
Rect(46,157,84,1),
Rect(45,138,1,1),
Rect(130,138,1,1),
Rect(45,157,1,1),
Rect(130,157,1,1),
Rect(46,139,84,18)));
}
void UIButton::render()
{
m_imageButtonUp->draw(m_rect);
UIElement::render();
g_fonts.get("tibia-8px-antialised")->renderText(m_text, m_rect, ALIGN_CENTER);
}

View File

@ -32,19 +32,17 @@
class UIButton : public UIElement
{
public:
UIButton(const std::string& text);
UIButton(const std::string& text) : UIElement(UI::Button),
m_text(text),
m_state(UI::ButtonUp) {
UIElement();
}
void render();
virtual UI::EControlType getControlType() const { return UI::Button; }
virtual void render();
private:
std::string m_text;
UI::EButtonState m_state;
ImagePtr m_imageButtonUp;
ImagePtr m_imageButtonDown;
ImagePtr m_imageButtonOver;
};
typedef std::shared_ptr<UIButton> UIButtonPtr;

View File

@ -51,7 +51,7 @@ namespace UI {
MessageBoxYesNo = MessageBoxYes | MessageBoxNo
};
enum EControlType
enum EElementType
{
Element,
Container,

View File

@ -24,7 +24,7 @@
#include "uicontainer.h"
UIContainerPtr g_gui(new UIContainer);
UIContainerPtr g_ui(new UIContainer);
void UIContainer::addChild(UIElementPtr child)
{
@ -96,6 +96,7 @@ void UIContainer::moveTo(const Point& pos)
void UIContainer::render()
{
UIElement::render();
for(auto it = m_children.begin(); it != m_children.end(); ++it) {
const UIElementPtr& child = (*it);
child->render();

View File

@ -33,7 +33,7 @@
class UIContainer : public UIElement
{
public:
UIContainer() : UIElement() { }
UIContainer(UI::EElementType type = UI::Container) : UIElement(type) { }
virtual ~UIContainer() { }
virtual void addChild(UIElementPtr child);
@ -52,7 +52,7 @@ public:
virtual void setActiveElement(UIElementPtr activeElement);
UIElementPtr getActiveElement() const { return m_activeElement; }
virtual UI::EControlType getControlType() const { return UI::Container; }
virtual UI::EElementType getElementType() const { return UI::Container; }
UIContainerPtr asUIContainer() { return std::static_pointer_cast<UIContainer>(shared_from_this()); }
@ -64,6 +64,6 @@ private:
void onMove(const Point& pos);
};
extern UIContainerPtr g_gui;
extern UIContainerPtr g_ui;
#endif // UICONTAINER_H

View File

@ -23,3 +23,33 @@
#include "uielement.h"
#include "uiskins.h"
UIElement::UIElement(UI::EElementType type) :
m_type(type)
{
// set default skin
setSkin(g_uiSkins.getElementSkin(type));
}
bool UIElement::setSkin(const std::string& skinName)
{
setSkin(g_uiSkins.getElementSkin(m_type, skinName));
return m_skin != NULL;
}
void UIElement::setSkin(UIElementSkin* skin)
{
if(skin && !m_rect.isValid()) {
m_rect.setSize(skin->getDefaultSize());
}
m_skin = skin;
}
void UIElement::render()
{
if(m_skin)
m_skin->draw(this);
}

View File

@ -29,6 +29,7 @@
#include "../input.h"
#include "../rect.h"
#include "uiconstants.h"
#include "uielementskin.h"
class UIContainer;
typedef std::shared_ptr<UIContainer> UIContainerPtr;
@ -39,13 +40,17 @@ typedef std::shared_ptr<UIElement> UIElementPtr;
class UIElement : public std::enable_shared_from_this<UIElement>
{
public:
UIElement() { }
UIElement(UI::EElementType type = UI::Element);
virtual ~UIElement() { }
virtual void render() { }
virtual void render();
virtual void update(int ticks, int elapsedTicks) { }
virtual bool onInputEvent(InputEvent *event) { return false; }
bool setSkin(const std::string& skinName);
void setSkin(UIElementSkin *skin);
UIElementSkin *getSkin() { return m_skin; }
virtual void setParent(UIContainerPtr parent) { m_parent = parent; }
UIContainerPtr getParent() const { return m_parent; }
@ -61,13 +66,14 @@ public:
virtual void setVisible(bool visible) { m_visible = visible; }
bool isVisible() const { return m_visible; }
virtual UI::EControlType getControlType() const { return UI::Element; }
UI::EElementType getElementType() const { return m_type; }
UIElementPtr asUIElement() { return shared_from_this(); }
protected:
UI::EControlType m_type;
UI::EElementType m_type;
UIContainerPtr m_parent;
UIElementSkin *m_skin;
Rect m_rect;
std::string m_name;
bool m_visible;

View File

@ -0,0 +1,78 @@
/* 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.
*/
#include "uielementskin.h"
#include "uielement.h"
#include "../borderedimage.h"
#include "../textures.h"
#include "uiskins.h"
void UIElementSkin::draw(UIElement *element)
{
const ImagePtr& image = m_stateImages.front();
if(image) {
image->draw(element->getRect());
}
}
void UIElementSkin::load(const YAML::Node& node)
{
if(node.FindValue("default size"))
node["default size"] >> m_defaultSize;
if(node.FindValue("bordered image")) {
const YAML::Node& child = node["bordered image"];
Rect left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight, center;
child["left border"] >> left;
child["right border"] >> right;
child["top border"] >> top;
child["bottom border"] >> bottom;
child["top left corner"] >> topLeft;
child["top right corner"] >> topRight;
child["bottom left corner"] >> bottomLeft;
child["bottom right corner"] >> bottomRight;
child["center"] >> center;
TexturePtr texture;
if(child.FindValue("image")) {
std::string textureName;
child["image"] >> textureName;
texture = g_textures.get(textureName);
} else {
texture = g_uiSkins.getDefaultTexture();
}
ImagePtr image = ImagePtr(new BorderedImage(texture,
left,
right,
top,
bottom,
topLeft,
topRight,
bottomLeft,
bottomRight,
center));
m_stateImages.push_back(image);
}
}

View File

@ -0,0 +1,56 @@
/* 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 UIELEMENTSKIN_H
#define UIELEMENTSKIN_H
#include "../prerequisites.h"
#include "uiconstants.h"
#include "../image.h"
#include "../rect.h"
class UIElement;
class UIElementSkin
{
public:
UIElementSkin(const std::string& name, UI::EElementType elementType) :
m_name(name),
m_elementType(elementType) { }
void load(const YAML::Node& node);
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; }
private:
std::string m_name;
UI::EElementType m_elementType;
Size m_defaultSize;
std::vector<ImagePtr> m_stateImages;
};
#endif // UIELEMENTSKIN_H

View File

@ -31,9 +31,7 @@
class UILabel : public UIElement
{
public:
UILabel() { }
virtual UI::EControlType getControlType() const { return UI::Label; }
UILabel() : UIElement(UI::Label) { }
};
#endif // UILABEL_H

View File

@ -23,24 +23,3 @@
#include "uipanel.h"
UIPanel::UIPanel()
{
m_boderedImage = BorderedImagePtr(new BorderedImage("ui.png",
Rect(0,214,5,32),
Rect(6,214,5,32),
Rect(43,214,32,5),
Rect(43,220,32,5),
Rect(43,225,5,5),
Rect(49,225,5,5),
Rect(43,230,5,5),
Rect(48,231,5,5),
Rect(11,214,32,32)));
}
void UIPanel::render()
{
m_boderedImage->draw(m_rect);
UIContainer::render();
}

View File

@ -32,14 +32,7 @@
class UIPanel : public UIContainer
{
public:
UIPanel();
void render();
virtual UI::EControlType getControlType() const { return UI::Panel; }
private:
BorderedImagePtr m_boderedImage;
UIPanel() : UIContainer(UI::Panel) { }
};
typedef std::shared_ptr<UIPanel> UIPanelPtr;

View File

@ -0,0 +1,92 @@
/* 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.
*/
#include "uiskins.h"
#include "../resources.h"
#include "../textures.h"
#include "uielementskin.h"
UISkins g_uiSkins;
bool UISkins::load(const std::string& file)
{
std::string fileContents = g_resources.loadTextFile(file);
if(!fileContents.size()) {
logFatal("Could not load skin file \"%s", file.c_str());
return false;
}
std::istringstream fin(fileContents);
try {
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc);
std::string defaultTexture;
doc["default skin image"] >> defaultTexture;
m_defaultTexture = g_textures.get("skins/" + defaultTexture);
{
const YAML::Node& node = doc["buttons"];
for(auto it = node.begin(); it != node.end(); ++it) {
std::string name;
it.first() >> name;
UIElementSkin *elementSkin = new UIElementSkin(name, UI::Button);
elementSkin->load(it.second());
m_elementSkins.push_back(elementSkin);
}
}
{
const YAML::Node& node = doc["panels"];
for(auto it = node.begin(); it != node.end(); ++it) {
std::string name;
it.first() >> name;
UIElementSkin *elementSkin = new UIElementSkin(name, UI::Panel);
elementSkin->load(it.second());
m_elementSkins.push_back(elementSkin);
}
}
} catch (YAML::ParserException& e) {
logError("Malformed font file \"%s\"", file.c_str());
return false;
}
return true;
}
UIElementSkin* UISkins::getElementSkin(UI::EElementType elementType, const std::string& name)
{
for(auto it = m_elementSkins.begin(); it != m_elementSkins.end(); ++it) {
UIElementSkin *skin = (*it);
if(elementType == skin->getElementType() && name == skin->getName()) {
return skin;
}
}
logWarning("Element skin '%s' not found", name.c_str());
return NULL;
}

View File

@ -0,0 +1,52 @@
/* 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 UISKIN_H
#define UISKIN_H
#include "../prerequisites.h"
#include "uicontainer.h"
#include "../texture.h"
class UIElementSkin;
class UISkins
{
public:
UISkins() { }
bool load(const std::string& file);
UIElementSkin *getElementSkin(UI::EElementType elementType, const std::string& name = "default");
TexturePtr getDefaultTexture() { return m_defaultTexture; }
private:
TexturePtr m_defaultTexture;
std::vector<UIElementSkin *> m_elementSkins;
};
extern UISkins g_uiSkins;
#endif // UISKIN_H

View File

@ -29,6 +29,7 @@
#include "menustate.h"
#include "teststate.h"
#include "framework/dispatcher.h"
#include "framework/ui/uiskins.h"
/// Catches signals so we can exit nicely
void signal_handler(int sig)
@ -108,6 +109,9 @@ int main(int argc, const char *argv[])
// init engine
g_engine.init();
// load UI skin
g_uiSkins.load("skins/tibiaskin.yml");
// state scope
{
std::shared_ptr<MenuState> initialState(new MenuState);

View File

@ -91,6 +91,7 @@ void MenuState::createMainMenu()
int y = 16;
m_menuPanel = UIPanelPtr(new UIPanel);
m_menuPanel->setSkin("roundedGridPanel");
recalculateMenuPanelPosition();
button = UIButtonPtr(new UIButton("Enter Game"));
@ -118,7 +119,7 @@ void MenuState::createMainMenu()
m_menuPanel->addChild(button);
y += 30;
g_gui->addChild(m_menuPanel);
g_ui->addChild(m_menuPanel);
}
void MenuState::recalculateMenuPanelPosition()