diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dde949b..fb91e8cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,8 @@ SET(SOURCES src/framework/ui/uilabel.cpp src/framework/ui/uiwindow.cpp src/framework/ui/uiwindowskin.cpp + src/framework/ui/uitextedit.cpp + src/framework/ui/uitexteditskin.cpp # network src/framework/net/connection.cpp diff --git a/src/framework/font.cpp b/src/framework/font.cpp index cfb46db3..4192fac6 100644 --- a/src/framework/font.cpp +++ b/src/framework/font.cpp @@ -63,7 +63,7 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize) } } // store glyph size - m_glyphsSize[glyph].setWidth(width); + m_glyphsSize[glyph].setSize(width, m_glyphHeight); } delete[] texturePixels; @@ -101,8 +101,7 @@ bool Font::load(const std::string& file) } // set glyphs height - for(int glyph = 32; glyph< 256; ++glyph) { - m_glyphsSize[glyph].setHeight(m_glyphHeight); + for(int glyph = 32; glyph < 256; ++glyph) { } calculateGlyphsWidthsAutomatically(glyphSize); @@ -124,7 +123,7 @@ bool Font::load(const std::string& file) m_glyphsTextureCoords[glyph].setRect(((glyph - 32) % numHorizontalGlyphs) * glyphSize.width(), ((glyph - 32) / numHorizontalGlyphs) * glyphSize.height(), m_glyphsSize[glyph].width(), - m_glyphsSize[glyph].height()); + m_glyphHeight); } } catch (YAML::ParserException& e) { @@ -253,7 +252,7 @@ Point* Font::calculateGlyphsPositions(const std::string& text, int align, Size * // protect buffer overflow on glyphsPostions int numGlyphs = text.length(); if(numGlyphs > 8192) - logFatal("A text was too long to render!"); + logFatal("could not calculate glyphs positions, text length is > 8192!"); // calculate lines width if((align & ALIGN_RIGHT || align & ALIGN_HORIZONTAL_CENTER) || textBoxSize) { @@ -281,7 +280,7 @@ Point* Font::calculateGlyphsPositions(const std::string& text, int align, Size * // new line or first glyph if(glyph == (uchar)'\n' || i == 0) { if(glyph == (uchar)'\n') { - virtualPos.y += m_glyphsSize[glyph].height() + m_glyphSpacing.height(); + virtualPos.y += m_glyphHeight + m_glyphSpacing.height(); lines++; } diff --git a/src/framework/ui/ui.h b/src/framework/ui/ui.h index e26fe19e..27d4d11c 100644 --- a/src/framework/ui/ui.h +++ b/src/framework/ui/ui.h @@ -35,5 +35,6 @@ #include "uilabel.h" #include "uiskins.h" #include "uiwindow.h" +#include "uitextedit.h" #endif // UI_H diff --git a/src/framework/ui/uibutton.cpp b/src/framework/ui/uibutton.cpp index decc5d2a..25c87a1e 100644 --- a/src/framework/ui/uibutton.cpp +++ b/src/framework/ui/uibutton.cpp @@ -38,9 +38,12 @@ 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) { + } else if(m_state == UI::ButtonDown && event.type == EV_MOUSE_LUP) { m_state = UI::ButtonUp; + if(getRect().contains(Point(event.mouse.x, event.mouse.y))) { + if(m_buttonClickCallback) + m_buttonClickCallback(); + } } return false; } diff --git a/src/framework/ui/uibutton.h b/src/framework/ui/uibutton.h index acff35a4..6fc91a4a 100644 --- a/src/framework/ui/uibutton.h +++ b/src/framework/ui/uibutton.h @@ -29,6 +29,8 @@ #include "uielement.h" #include "../borderedimage.h" +typedef std::function Callback; + class UIButton : public UIElement { public: @@ -43,9 +45,12 @@ public: UI::EButtonState getState() { return m_state; } + void onClick(const Callback& callback) { m_buttonClickCallback = callback; } + private: std::string m_text; UI::EButtonState m_state; + Callback m_buttonClickCallback; }; typedef std::shared_ptr UIButtonPtr; diff --git a/src/framework/ui/uibuttonskin.h b/src/framework/ui/uibuttonskin.h index 268348fa..8caaa0d3 100644 --- a/src/framework/ui/uibuttonskin.h +++ b/src/framework/ui/uibuttonskin.h @@ -32,7 +32,8 @@ class UIButtonSkin : public UIElementSkin { public: - UIButtonSkin(const std::string& name, UI::EElementType elementType) :UIElementSkin(name, elementType) { } + UIButtonSkin(const std::string& name) : + UIElementSkin(name, UI::Button) { } void load(const YAML::Node& node); void draw(UIElement *element); diff --git a/src/framework/ui/uiconstants.h b/src/framework/ui/uiconstants.h index 16774979..66d34923 100644 --- a/src/framework/ui/uiconstants.h +++ b/src/framework/ui/uiconstants.h @@ -58,7 +58,7 @@ namespace UI { Panel, Window, Label, - TextBox, + TextEdit, Button, CheckBox }; diff --git a/src/framework/ui/uilabel.cpp b/src/framework/ui/uilabel.cpp index e1cc5048..af7d6dc7 100644 --- a/src/framework/ui/uilabel.cpp +++ b/src/framework/ui/uilabel.cpp @@ -23,4 +23,26 @@ #include "uilabel.h" +#include "../fonts.h" + +UILabel::UILabel(const std::string& text, Font* font) : + UIElement(UI::Label), + m_text(text), + m_font(font) +{ + if(!font) + m_font = g_fonts.get("tibia-10px-antialised"); + setSize(m_font->calculateTextRectSize(text)); +} + +void UILabel::render() +{ + m_font->renderText(m_text, getRect(), ALIGN_LEFT, Color(0xFFBFBFBF)); +} + +void UILabel::setText(const std::string& text) +{ + setSize(m_font->calculateTextRectSize(text)); + m_text = text; +} diff --git a/src/framework/ui/uilabel.h b/src/framework/ui/uilabel.h index d0deb919..4b2ab7f9 100644 --- a/src/framework/ui/uilabel.h +++ b/src/framework/ui/uilabel.h @@ -28,10 +28,23 @@ #include "../prerequisites.h" #include "uielement.h" +class Font; + class UILabel : public UIElement { public: - UILabel() : UIElement(UI::Label) { } + UILabel(const std::string& text, Font *font = NULL); + + void render(); + + void setText(const std::string& text); + const std::string& getText() const { return m_text; } + +private: + std::string m_text; + Font *m_font; }; +typedef std::shared_ptr UILabelPtr; + #endif // UILABEL_H diff --git a/src/framework/ui/uiskins.cpp b/src/framework/ui/uiskins.cpp index e6d45225..62b72b4b 100644 --- a/src/framework/ui/uiskins.cpp +++ b/src/framework/ui/uiskins.cpp @@ -28,6 +28,7 @@ #include "uielementskin.h" #include "uibuttonskin.h" #include "uiwindowskin.h" +#include "uitexteditskin.h" UISkins g_uiSkins; @@ -63,7 +64,7 @@ bool UISkins::load(const std::string& file) std::string name; it.first() >> name; - UIButtonSkin *skin = new UIButtonSkin(name, UI::Button); + UIElementSkin *skin = new UIButtonSkin(name); skin->load(it.second()); m_elementSkins.push_back(skin); } @@ -87,11 +88,37 @@ bool UISkins::load(const std::string& file) std::string name; it.first() >> name; - UIWindowSkin *skin = new UIWindowSkin(name, UI::Window); + UIElementSkin *skin = new UIWindowSkin(name); skin->load(it.second()); m_elementSkins.push_back(skin); } } + + { + const YAML::Node& node = doc["labels"]; + for(auto it = node.begin(); it != node.end(); ++it) { + std::string name; + it.first() >> name; + + UIElementSkin *skin = new UIElementSkin(name, UI::Label); + skin->load(it.second()); + m_elementSkins.push_back(skin); + } + } + + { + const YAML::Node& node = doc["text edits"]; + for(auto it = node.begin(); it != node.end(); ++it) { + std::string name; + it.first() >> name; + + UIElementSkin *skin = new UITextEditSkin(name); + skin->load(it.second()); + m_elementSkins.push_back(skin); + } + } + + } catch (YAML::ParserException& e) { logError("Malformed font file \"%s\"", file.c_str()); return false; diff --git a/src/framework/ui/uitextedit.cpp b/src/framework/ui/uitextedit.cpp new file mode 100644 index 00000000..9da68902 --- /dev/null +++ b/src/framework/ui/uitextedit.cpp @@ -0,0 +1,45 @@ +/* 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 "uitextedit.h" +#include "../fonts.h" + +UITextEdit::UITextEdit(Font* font) : + UIElement(UI::TextEdit), + m_font(font) +{ + if(!font) + m_font = g_fonts.get("tibia-10px-antialised"); +} + +void UITextEdit::render() +{ + UIElement::render(); + m_font->renderText(m_text, getRect(), ALIGN_LEFT, Color(0xFFBFBFBF)); +} + +void UITextEdit::setText(const std::string& text) +{ + m_text = text; +} diff --git a/src/framework/ui/uitextedit.h b/src/framework/ui/uitextedit.h new file mode 100644 index 00000000..7ada3721 --- /dev/null +++ b/src/framework/ui/uitextedit.h @@ -0,0 +1,50 @@ +/* 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 UITEXTEDIT_H +#define UITEXTEDIT_H + +#include "../prerequisites.h" +#include "uielement.h" + +class Font; + +class UITextEdit : public UIElement +{ +public: + UITextEdit(Font *font = NULL); + + void render(); + + void setText(const std::string& text); + const std::string& getText() const { return m_text; } + +private: + std::string m_text; + Font *m_font; +}; + +typedef std::shared_ptr UITextEditPtr; + +#endif // UITEXTEDIT_H diff --git a/src/framework/ui/uitexteditskin.cpp b/src/framework/ui/uitexteditskin.cpp new file mode 100644 index 00000000..33d422db --- /dev/null +++ b/src/framework/ui/uitexteditskin.cpp @@ -0,0 +1,26 @@ +/* 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 "uitexteditskin.h" + diff --git a/src/framework/ui/uitexteditskin.h b/src/framework/ui/uitexteditskin.h new file mode 100644 index 00000000..7e79e2cf --- /dev/null +++ b/src/framework/ui/uitexteditskin.h @@ -0,0 +1,40 @@ +/* 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 UITEXTEDITSKIN_H +#define UITEXTEDITSKIN_H + +#include "../prerequisites.h" +#include "uiconstants.h" +#include "uielementskin.h" + +class UITextEditSkin : public UIElementSkin +{ +public: + UITextEditSkin(const std::string& name) : + UIElementSkin(name, UI::TextEdit) { } + +}; + +#endif // UITEXTEDITSKIN_H diff --git a/src/framework/ui/uiwindowskin.h b/src/framework/ui/uiwindowskin.h index fc97e2b6..09f917db 100644 --- a/src/framework/ui/uiwindowskin.h +++ b/src/framework/ui/uiwindowskin.h @@ -32,8 +32,8 @@ class UIWindowSkin : public UIElementSkin { public: - UIWindowSkin(const std::string& name, UI::EElementType elementType) : - UIElementSkin(name, elementType) { } + UIWindowSkin(const std::string& name) : + UIElementSkin(name, UI::Window) { } void load(const YAML::Node& node); void draw(UIElement *element); diff --git a/src/menustate.cpp b/src/menustate.cpp index 12e8105b..15f87328 100644 --- a/src/menustate.cpp +++ b/src/menustate.cpp @@ -82,7 +82,6 @@ void MenuState::render() void MenuState::createMainMenu() { - UIButtonPtr button; int y = 0; m_menuPanel = UIPanelPtr(new UIPanel); @@ -93,13 +92,14 @@ void MenuState::createMainMenu() m_menuPanel->setMargin(0, 60, 70, 0); g_ui->addChild(m_menuPanel); - button = UIButtonPtr(new UIButton("Enter Game")); - button->anchorTop(m_menuPanel->top()); - button->anchorHorizontalCenter(m_menuPanel->horizontalCenter()); - button->setMargin(y += 16); - m_menuPanel->addChild(button); + // main menu + UIButtonPtr enterGameButton = UIButtonPtr(new UIButton("Enter Game")); + enterGameButton->anchorTop(m_menuPanel->top()); + enterGameButton->anchorHorizontalCenter(m_menuPanel->horizontalCenter()); + enterGameButton->setMargin(y += 16); + m_menuPanel->addChild(enterGameButton); - button = UIButtonPtr(new UIButton("Access Account")); + UIButtonPtr button = UIButtonPtr(new UIButton("Access Account")); button->anchorTop(m_menuPanel->top()); button->anchorHorizontalCenter(m_menuPanel->horizontalCenter()); button->setMargin(y += 30); @@ -122,11 +122,68 @@ void MenuState::createMainMenu() button->anchorTop(m_menuPanel->top()); button->anchorHorizontalCenter(m_menuPanel->horizontalCenter()); button->setMargin(y += 30); + button->onClick([]{ g_engine.stop(); }); m_menuPanel->addChild(button); + // login window UIWindowPtr window(new UIWindow("Enter Game")); window->setSize(Size(236, 178)); window->anchorHorizontalCenter(g_ui->horizontalCenter()); window->anchorVerticalCenter(g_ui->verticalCenter()); + window->setVisible(false); g_ui->addChild(window); + + UILabelPtr label(new UILabel("Account name:")); + label->anchorLeft(window->left()); + label->anchorTop(window->top()); + label->setMargin(18, 33); + window->addChild(label); + + label = UILabelPtr(new UILabel("Password:")); + label->anchorLeft(window->left()); + label->anchorTop(window->top()); + label->setMargin(18, 62); + window->addChild(label); + + label = UILabelPtr(new UILabel("If you don't have\nan account yet:")); + label->anchorLeft(window->left()); + label->anchorTop(window->top()); + label->setMargin(18, 87); + window->addChild(label); + + button = UIButtonPtr(new UIButton("Create Account")); + button->anchorLeft(window->left()); + button->anchorTop(window->top()); + button->setMargin(132, 94); + window->addChild(button); + + button = UIButtonPtr(new UIButton("Ok")); + button->setSize(Size(43, 20)); + button->anchorRight(window->right()); + button->anchorBottom(window->bottom()); + button->setMargin(0, 0, 10, 66); + button->onClick([window]{ window->setVisible(false); }); + window->addChild(button); + + button = UIButtonPtr(new UIButton("Cancel")); + button->setSize(Size(43, 20)); + button->anchorRight(window->right()); + button->anchorBottom(window->bottom()); + button->setMargin(0, 0, 10, 13); + button->onClick([window]{ window->setVisible(false); }); + window->addChild(button); + + UITextEditPtr textEdit(new UITextEdit); + textEdit->anchorRight(window->right()); + textEdit->anchorTop(window->top()); + textEdit->setMargin(32, 0, 0, 18); + window->addChild(textEdit); + + textEdit = UITextEditPtr(new UITextEdit); + textEdit->anchorRight(window->right()); + textEdit->anchorTop(window->top()); + textEdit->setMargin(61, 0, 0, 18); + window->addChild(textEdit); + + enterGameButton->onClick([window] { window->setVisible(true); }); }