rework ui related scripting stuff

master
Eduardo Bart 13 years ago
parent 571801ae39
commit bddcfb08fd

@ -0,0 +1,4 @@
-- some aliases
loadUI = UI.load
rootUI = UI.getRootContainer()

@ -0,0 +1,4 @@
require 'aliases'
require 'enums'
require 'util'

@ -0,0 +1,8 @@
-- AnchorPoint
AnchorNone = 0
AnchorTop = 1
AnchorBottom = 2
AnchorLeft = 3
AnchorRight = 4
AnchorVerticalCenter = 5
AnchorHorizontalCenter = 6

@ -0,0 +1,8 @@
title: Core
notes: Core utilities used by other modules
author: edubart
version: 1
website: https://github.com/edubart/otclient
enabled: true
script: core.lua

@ -0,0 +1,5 @@
function createEmptyFunction()
local emptyFunction = function() end
return emptyFunction
end

@ -0,0 +1,57 @@
function EnterGame_connectToLoginServer()
-- create login protocol
local protocolLogin = ProtocolLogin.new()
-- used to recreate enter game window
local recreateEnterGame = function()
loadUI("ui/entergamewindow")
end
-- display loading message box
local loadBox = displayCancelBox("Please wait", "Connecting..")
-- cancel loading callback
loadBox.onCancel = function()
-- cancel protocol and reacreate enter game window
protocolLogin:cancel()
recreateEnterGame()
end
-- error callback
protocolLogin.onError = function(error)
-- destroy loading message box
loadBox:destroy()
-- display error message
local errorBox = displayErrorBox("Login Error", error)
-- cancel protocol and reacreate enter game window
self.cancel()
errorBox.onOk = recreateEnterGame
end
-- motd callback
protocolLogin.onMotd = function(motd)
-- destroy loading message box
loadBox:destroy()
-- display motd
local motdNumber = string.sub(motd, 0, string.find(motd, "\n"))
local motdText = string.sub(motd, string.find(motd, "\n") + 1, string.len(motd))
local motdBox = displayInfoBox("Message of the day", motdText)
-- cancel protocol and reacreate enter game window
self.cancel()
motdBox.onOk = recreateEnterGame
end
-- get account and password and login
local enterGameWindow = rootUI:child("enterGameWindow")
local account = enterGameWindow:child("accountNameTextEdit").text
local password = enterGameWindow:child("passwordTextEdit").text
protocolLogin:login(account, password)
-- destroy enter game window
enterGameWindow:destroy()
end

@ -0,0 +1,16 @@
require 'entergame'
function initializeApplication()
mainMenu = loadUI("ui/mainmenu")
end
function terminateApplication()
App.exit()
end
-- here is where everything starts
if not initialized then
initializeApplication()
App.onClose = terminateApplication
initialized = true
end

@ -1,63 +0,0 @@
-- menu state
function onEnterMenuState()
mainMenu = UI.load("mainmenu.yml")
end
function onLeaveMenuState()
end
function onApplicationClose()
onLeaveMenuState()
App.exit()
end
function enterGame_onOkClicked()
local enterGameWindow = UI.getRootContainer():child("enterGameWindow")
enterGameWindow.visible = false
local loadMessageBox = messageBox("Please wait", "Connecting..")
loadMessageBox.onDestroy = function()
--TODO: cancel protocol
enterGameWindow.visible = true
protocolLogin = nil
end
protocolLogin = ProtocolLogin.new()
protocolLogin.onError = function(error)
loadMessageBox.onDestroy = nil
loadMessageBox:destroy()
local msgBox = messageBox("Login Error", error)
msgBox.onDestroy = function()
enterGameWindow.visible = true
end
protocolLogin = nil
end
protocolLogin.onMotd = function(motd)
loadMessageBox.onDestroy = nil
loadMessageBox:destroy()
local motdNumber = string.sub(motd, 0, string.find(motd, "\n"))
local motdText = string.sub(motd, string.find(motd, "\n") + 1, string.len(motd))
local msgBox = messageBox("Message of the day", motdText)
msgBox.onDestroy = function()
enterGameWindow.visible = true
end
protocolLogin = nil
end
local account = enterGameWindow:child("accountNameTextEdit").text
local password = enterGameWindow:child("passwordTextEdit").text
account = "tibialua0"
password = "lua123456"
protocolLogin:login(account, password)
end
-- here is where everything starts
if not initialStateLoaded then
onEnterMenuState()
App.onClose = onApplicationClose
initialStateLoaded = true
end

@ -3,7 +3,7 @@
size: [236, 178]
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
onLoad: self.locked = true
onLoad: self:setLocked()
%label#accountNameLabel
text: Account name
@ -34,7 +34,7 @@
anchors.top: parent.top
margin.top: 94
margin.left: 132
onClick: messageBox("Error", "Not implemented yet")
onClick: displayErrorBox("Error", "Not implemented yet")
%button#okButton
text: Ok
@ -43,7 +43,7 @@
anchors.bottom: parent.bottom
margin.bottom: 10
margin.right: 66
onClick: enterGame_onOkClicked()
onClick: EnterGame_connectToLoginServer()
%button#cancelButton
text: Cancel

@ -5,22 +5,6 @@
anchors.top: parent.top
anchors.bottom: parent.bottom
%panel#icos4d
skin:
image: /skins/lightness/mouse.png
anchors.left: parent.left
anchors.top: parent.top
margin.left: -2
margin.top: 70
%panel#mouse
skin:
image: /skins/lightness/icos4d.png
anchors.right: parent.right
anchors.bottom: parent.bottom
margin.left: 60
margin.top: 70
%panel#mainMenu
skin: roundedGridPanel
size: [117, 171]
@ -34,32 +18,32 @@
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 16
onClick: UI.load("entergamewindow.yml")
onClick: UI.load("entergamewindow")
%button#accessAccountButton
text: Access Account
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 46
onClick: messageBox("Error", "Not implemented yet")
onClick: displayErrorBox("Error", "Not implemented yet")
%button#optionsButton
text: Options
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 76
onClick: UI.load("optionswindow.yml")
onClick: UI.load("optionswindow")
%button#infoButton
text: Info
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 106
onClick: UI.load("infowindow.yml")
onClick: UI.load("infowindow")
%button#exitGameButton
text: Exit
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 136
onClick: onApplicationClose()
onClick: terminateApplication()

@ -1,34 +1,86 @@
MessageBox = {}
MessageBox.__index = MessageBox
function MessageBox.create(title, text)
local msgBox = {}
setmetatable(msgBox, MessageBox)
local window = UI.load("messagebox.yml")
window.locked = true
window.title = title
window:child("textLabel").text = text
window:child("okButton").onClick = function()
self.parent:destroy()
end
window.onDestroy = function()
if msgBox.onDestroy then
msgBox.onDestroy()
end
end
msgBox.window = window
return msgBox
-- messagebox flags
MessageBoxOk = 1
MessageBoxCancel = 2
function MessageBox.create(title, text, flags)
local box = {}
setmetatable(box, MessageBox)
-- create messagebox window
local window = UIWindow.new("messageBoxWindow", rootUI)
window.title = title
window:centerIn(rootUI)
window:setLocked()
-- create messagebox label
local label = UILabel.new("messageBoxLabel", window)
label.text = text
label:addAnchor(AnchorHorizontalCenter, window, AnchorHorizontalCenter)
label:addAnchor(AnchorTop, window, AnchorTop)
label:setMargin(27, 0)
-- set window size based on label size
window.width = label.width + 40
window.height = label.height + 64
-- setup messagebox first button
local buttonText
local button1 = UIButton.new("messageBoxButton1", window)
button1:addAnchor(AnchorBottom, window, AnchorBottom)
button1:addAnchor(AnchorRight, window, AnchorRight)
button1:setMargin(10)
if flags == MessageBoxOk then
buttonText = "Ok"
box.onOk = createEmptyFunction()
button1.onClick = function()
box.onOk()
box:destroy()
end
elseif flags == MessageBoxCancel then
buttonText = "Cancel"
box.onCancel = createEmptyFunction()
button1.onClick = function()
box.onCancel()
box:destroy()
end
end
button1.text = buttonText
box.window = window
return box
end
function MessageBox:destroy()
if self.window then
self.window:destroy()
self.window = nil
end
if self.onDestroy then
self.onDestroy()
self.onDestroy = nil
end
if self.window then
self.window:destroy()
self.window = nil
end
self.onOk = nil
self.onCancel = nil
end
-- shortcuts for creating message boxes
function displayMessageBox(title, text, flags)
return MessageBox.create(title, text, flags)
end
function displayErrorBox(title, text)
return MessageBox.create(title, text, MessageBoxOk)
end
function displayInfoBox(title, text)
return MessageBox.create(title, text, MessageBoxOk)
end
function messageBox(title, text)
return MessageBox.create(title, text)
function displayCancelBox(title, text)
return MessageBox.create(title, text, MessageBoxCancel)
end

@ -1,18 +0,0 @@
%window#messageBoxWindow
size: [192, 78]
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
%label#textLabel
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
margin.top: 27
%button#okButton
text: Ok
size: [43, 20]
anchors.right: parent.right
anchors.bottom: parent.bottom
margin.bottom: 10
margin.right: 10

@ -0,0 +1,8 @@
title: Message box
notes: Functions for creating message boxes
author: edubart
version: 1
website: https://github.com/edubart/otclient
enabled: true
script: messagebox.lua

@ -5,8 +5,8 @@
OTMLParser::OTMLParser(std::istream& in, std::string what) :
m_currentDepth(0), m_currentLine(0),
m_rootNode(new OTMLNode), m_currentParent(m_rootNode), m_previousNode(0),
m_what(what), m_in(in)
m_rootNode(new OTMLNode(what)), m_currentParent(m_rootNode), m_previousNode(0),
m_in(in)
{
parse();
}
@ -20,8 +20,8 @@ void OTMLParser::throwError(const std::string& message, int line)
{
std::stringstream ss;
ss << "OTML syntax error";
if(!m_what.empty())
ss << " in '" << m_what << "'";
if(!what().empty())
ss << " in '" << what() << "'";
if(line > 0)
ss << " at line " << line;
ss << ": " << message;

@ -1,11 +1,9 @@
#ifndef OTMLPARSER_H
#define OTMLPARSER_H
#include <string>
#include <vector>
#include <istream>
#include <otml/otmlnode.h>
class OTMLNode;
#include <istream>
class OTMLParser
{
@ -14,7 +12,7 @@ public:
~OTMLParser();
OTMLNode* getDocument() const { return m_rootNode; }
std::string what() { return m_what; }
std::string what() { return m_rootNode->what(); }
void throwError(const std::string& message, int line);
@ -33,7 +31,6 @@ private:
OTMLNode* m_rootNode;
OTMLNode* m_currentParent;
OTMLNode* m_previousNode;
std::string m_what;
std::istream& m_in;
};

@ -593,7 +593,7 @@ int ScriptContext::luaPackageLoader(lua_State* L)
if(g_resources.fileExists(fileName)) {
std::stringstream fin;
if(g_resources.loadFile(fileName, fin))
luaL_loadbuffer(L, fin.str().c_str(), fin.str().length(), fileName.c_str());
luaL_loadbuffer(L, fin.str().c_str(), fin.str().length(), ("@" + g_resources.resolvePath(fileName)).c_str());
} else {
lua_pushfstring(L, "\n\tcould not load lua script " LUA_QS, fileName.c_str());
}

@ -7,112 +7,116 @@
#include <core/dispatcher.h>
#include "../../protocollogin.h"
void registerScriptFunctions()
{
// App
g_lua.registerModule("App");
g_lua.registerMemberFunction("exit", &lua_App_exit);
// UI
g_lua.registerClass("UI");
g_lua.registerMemberFunction("load", &lua_UI_load);
g_lua.registerMemberFunction("getRootContainer", &lua_UI_getRootContainer);
// UIElement
g_lua.registerClass("UIElement");
g_lua.registerMemberField("id", &lua_UIElement_getId, &lua_UIElement_setId);
g_lua.registerMemberField("enabled", &lua_UIElement_isEnabled, &lua_UIElement_setEnabled);
g_lua.registerMemberField("visible", &lua_UIElement_isVisible, &lua_UIElement_setVisible);
g_lua.registerMemberField("focused", &lua_UIElement_isFocused, &lua_UIElement_setFocused);
g_lua.registerMemberField("parent", &lua_UIElement_getParent, &lua_UIElement_setParent);
g_lua.registerMemberField("locked", NULL, &lua_UIElement_setLocked);
g_lua.registerMemberFunction("destroy", &lua_UIElement_destroy);
// UIContainer
g_lua.registerClass("UIContainer", "UIElement");
g_lua.registerMemberFunction("child", &lua_UIContainer_getChild);
g_lua.registerMemberFunction("children", &lua_UIContainer_getChildren);
// UILabel
g_lua.registerClass("UILabel", "UIElement");
g_lua.registerMemberField("text", &lua_UILabel_getText, &lua_UILabel_setText);
// UIButton
g_lua.registerClass("UIButton", "UIElement");
// UITextEdit
g_lua.registerClass("UITextEdit", "UIElement");
g_lua.registerMemberField("text", &lua_UITextEdit_getText, &lua_UITextEdit_setText);
// UIWindow
g_lua.registerClass("UIWindow", "UIContainer");
g_lua.registerMemberField("title", &lua_UIWindow_getTitle, &lua_UIWindow_setTitle);
// Protocol
g_lua.registerClass("ProtocolLogin");
g_lua.registerMemberFunction("new", []{
ProtocolLoginPtr protocolLogin(new ProtocolLogin);
g_lua.pushClassInstance(protocolLogin);
return 1;
});
g_lua.registerMemberFunction("login", []{
std::string accountPassword = g_lua.popString();
std::string accountName = g_lua.popString();
if(ProtocolLoginPtr protocolLogin = boost::dynamic_pointer_cast<ProtocolLogin>(g_lua.popClassInstance()))
protocolLogin->login(accountName, accountPassword);
return 0;
});
}
#include <boost/algorithm/string.hpp>
////////////////////////////////////////////////////////////////////////////////
// App module
// App
int lua_App_exit()
{
int lua_App_exit() {
g_engine.stop();
return 1;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// UI module
// UI
int lua_UI_load()
{
int lua_UI_load() {
UIContainerPtr parent;
if(g_lua.getStackSize() > 1) {
if(g_lua.getStackSize() > 1)
parent = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance());
} else {
else
parent = UIContainer::getRoot();
}
std::string uiFile = g_lua.popString();
if(!boost::ends_with(uiFile, ".otml"))
uiFile.append(".otml");
UIElementPtr element;
if(parent)
if(parent) {
element = g_uiLoader.loadFromFile(uiFile.c_str(), parent);
else
g_lua.reportErrorWithTraceback("invalid parent container");
if(!element) {
g_lua.reportFuncErrorWithTraceback("failed to load UI");
}
} else
g_lua.reportFuncErrorWithTraceback("invalid parent container");
g_lua.pushClassInstance(element);
return 1;
}
int lua_UI_getRootContainer()
{
int lua_UI_getRootContainer() {
UIContainerPtr rootContainer = UIContainer::getRoot();
g_lua.pushClassInstance(rootContainer);
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UIElement
int lua_UIElement_getId()
UIElementPtr lua_createUIElement(UI::ElementType elementType)
{
std::string id;
UIContainerPtr parent;
if(g_lua.getStackSize() > 1)
parent = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance());
if(g_lua.getStackSize() > 0) {
if(g_lua.isString())
id = g_lua.popString();
else
parent = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance());
}
UIElementPtr element;
switch(elementType) {
case UI::Element:
element = UIElementPtr(new UIElement);
break;
case UI::Container:
element = UIElementPtr(new UIContainer);
break;
case UI::Label:
element = UIElementPtr(new UILabel);
break;
case UI::Button:
element = UIElementPtr(new UIButton);
break;
case UI::TextEdit:
element = UIElementPtr(new UITextEdit);
break;
case UI::Window:
element = UIElementPtr(new UIWindow);
break;
default:
break;
}
if(element) {
if(!id.empty())
element->setId(id);
if(parent)
parent->addChild(element);
element->applyDefaultSkin();
}
return element;
}
int lua_UIElement_new() {
g_lua.pushClassInstance(lua_createUIElement(UI::Element));
return 1;
}
int lua_UIElement_getId() {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushString(element->getId());
else
@ -120,16 +124,14 @@ int lua_UIElement_getId()
return 1;
}
int lua_UIElement_setId()
{
int lua_UIElement_setId() {
std::string id = g_lua.popString();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setId(id);
return 1;
return 0;
}
int lua_UIElement_isEnabled()
{
int lua_UIElement_isEnabled() {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushBoolean(element->isEnabled());
else
@ -137,16 +139,14 @@ int lua_UIElement_isEnabled()
return 1;
}
int lua_UIElement_setEnabled()
{
int lua_UIElement_setEnabled() {
bool enabled = g_lua.popBoolean();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setEnabled(enabled);
return 1;
return 0;
}
int lua_UIElement_isVisible()
{
int lua_UIElement_isVisible() {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushBoolean(element->isVisible());
else
@ -154,16 +154,14 @@ int lua_UIElement_isVisible()
return 1;
}
int lua_UIElement_setVisible()
{
int lua_UIElement_setVisible() {
bool visible = g_lua.popBoolean();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setVisible(visible);
return 1;
return 0;
}
int lua_UIElement_isFocused()
{
int lua_UIElement_isFocused() {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushBoolean(element->isFocused());
else
@ -171,16 +169,44 @@ int lua_UIElement_isFocused()
return 1;
}
int lua_UIElement_setFocused()
{
int lua_UIElement_setFocused() {
bool focused = g_lua.popBoolean();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setFocused(focused);
return 0;
}
int lua_UIElement_getWidth() {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushInteger(element->getWidth());
else
g_lua.pushInteger(0);
return 1;
}
int lua_UIElement_getParent()
{
int lua_UIElement_setWidth() {
int width = g_lua.popInteger();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setWidth(width);
return 0;
}
int lua_UIElement_getHeight() {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushInteger(element->getHeight());
else
g_lua.pushInteger(0);
return 1;
}
int lua_UIElement_setHeight() {
int height = g_lua.popInteger();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setHeight(height);
return 0;
}
int lua_UIElement_getParent() {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushClassInstance(element->getParent());
else
@ -188,44 +214,98 @@ int lua_UIElement_getParent()
return 1;
}
int lua_UIElement_setParent()
{
int lua_UIElement_setParent() {
UIContainerPtr parent = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance());
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setParent(parent);
return 1;
return 0;
}
int lua_UIElement_setLocked()
{
bool locked = g_lua.popBoolean();
int lua_UIElement_setLocked() {
bool locked = true;
if(g_lua.getStackSize() > 1)
locked = g_lua.popBoolean();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance())) {
if(UIContainerPtr container = element->getParent()) {
if(locked)
container->lockElement(element);
else
container->unlockElement(element);
}
} else
g_lua.reportFuncErrorWithTraceback("locking failed, element has no parent");
}
return 0;
}
int lua_UIElement_setMargin() {
int top = 0, right = 0, bottom = 0, left = 0;
if(g_lua.getStackSize() == 5) {
left = g_lua.popInteger();
bottom = g_lua.popInteger();
right = g_lua.popInteger();
top = g_lua.popInteger();
} else if(g_lua.getStackSize() == 3) {
left = right = g_lua.popInteger();
top = bottom = g_lua.popInteger();
} else if(g_lua.getStackSize() == 2) {
top = right = bottom = left = g_lua.popInteger();
} else {
g_lua.reportFuncErrorWithTraceback("invalid element");
g_lua.reportFuncErrorWithTraceback("invalid number of arguments");
}
return 1;
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setMargin(top, right, bottom, left);
return 0;
}
int lua_UIElement_destroy()
{
int lua_UIElement_destroy() {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->destroyLater();
g_dispatcher.addTask(boost::bind(&ScriptContext::collectGarbage, &g_lua));
return 1;
return 0;
}
int lua_UIElement_centerIn() {
std::string targetId;
if(g_lua.isString())
targetId = g_lua.popString();
else if(UIElementPtr target = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
targetId = target->getId();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->centerIn(targetId);
return 0;
}
int lua_UIElement_addAnchor() {
AnchorPoint targetEdge = (AnchorPoint)g_lua.popInteger();
std::string targetId;
if(g_lua.isString())
targetId = g_lua.popString();
else if(UIElementPtr target = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
targetId = target->getId();
AnchorPoint anchoredEdge = (AnchorPoint)g_lua.popInteger();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->addAnchor(anchoredEdge, AnchorLine(targetId, targetEdge));
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// UIContainer
int lua_UIContainer_getChild()
{
int lua_UIContainer_new() {
g_lua.pushClassInstance(lua_createUIElement(UI::Container));
return 1;
}
int lua_UIContainer_child() {
std::string id = g_lua.popString();
if(UIContainerPtr container = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance()))
g_lua.pushClassInstance(container->getChildById(id));
@ -234,8 +314,7 @@ int lua_UIContainer_getChild()
return 1;
}
int lua_UIContainer_getChildren()
{
int lua_UIContainer_getChildren() {
if(UIContainerPtr container = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance())) {
g_lua.newTable();
foreach(const UIElementPtr& child, container->getChildren()) {
@ -248,19 +327,32 @@ int lua_UIContainer_getChildren()
return 1;
}
int lua_UIContainer_addChild() {
UIElementPtr child = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance());
UIContainerPtr container = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance());
if(container && child)
container->addChild(child);
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// UILabel
int lua_UILabel_setText()
{
int lua_UILabel_new() {
g_lua.pushClassInstance(lua_createUIElement(UI::Label));
return 1;
}
int lua_UILabel_setText() {
std::string text = g_lua.popString();
if(UILabelPtr label = boost::dynamic_pointer_cast<UILabel>(g_lua.popClassInstance()))
label->setText(text);
return 1;
return 0;
}
int lua_UILabel_getText()
{
int lua_UILabel_getText() {
if(UILabelPtr label = boost::dynamic_pointer_cast<UILabel>(g_lua.popClassInstance()))
g_lua.pushString(label->getText());
else
@ -269,19 +361,48 @@ int lua_UILabel_getText()
}
////////////////////////////////////////////////////////////////////////////////
// UILabel
// UIButton
int lua_UITextEdit_setText()
{
int lua_UIButton_new() {
g_lua.pushClassInstance(lua_createUIElement(UI::Button));
return 1;
}
int lua_UIButton_setText() {
std::string text = g_lua.popString();
if(UIButtonPtr button = boost::dynamic_pointer_cast<UIButton>(g_lua.popClassInstance()))
button->setText(text);
return 0;
}
int lua_UIButton_getText() {
if(UIButtonPtr button = boost::dynamic_pointer_cast<UIButton>(g_lua.popClassInstance()))
g_lua.pushString(button->getText());
else
g_lua.pushNil();
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UITextEdit
int lua_UITextEdit_new() {
g_lua.pushClassInstance(lua_createUIElement(UI::TextEdit));
return 1;
}
int lua_UITextEdit_setText() {
std::string text = g_lua.popString();
if(UITextEditPtr textEdit = boost::dynamic_pointer_cast<UITextEdit>(g_lua.popClassInstance()))
textEdit->setText(text);
return 1;
return 0;
}
int lua_UITextEdit_getText()
{
int lua_UITextEdit_getText() {
if(UITextEditPtr textEdit = boost::dynamic_pointer_cast<UITextEdit>(g_lua.popClassInstance()))
g_lua.pushString(textEdit->getText());
else
@ -289,22 +410,152 @@ int lua_UITextEdit_getText()
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UIWindow
int lua_UIWindow_setTitle()
{
int lua_UIWindow_new() {
g_lua.pushClassInstance(lua_createUIElement(UI::Window));
return 1;
}
int lua_UIWindow_setTitle() {
std::string title = g_lua.popString();
if(UIWindowPtr window = boost::dynamic_pointer_cast<UIWindow>(g_lua.popClassInstance()))
window->setTitle(title);
return 1;
return 0;
}
int lua_UIWindow_getTitle()
{
int lua_UIWindow_getTitle() {
if(UIWindowPtr window = boost::dynamic_pointer_cast<UIWindow>(g_lua.popClassInstance()))
g_lua.pushString(window->getTitle());
else
g_lua.pushNil();
return 1;
}
void registerScriptFunctions()
{
////////////////////////////////////////////////////////////////////////////////
// App
g_lua.registerModule("App");
// App.exit()
g_lua.registerMemberFunction("exit", &lua_App_exit);
////////////////////////////////////////////////////////////////////////////////
// UI
g_lua.registerClass("UI");
// UI.load(file, [parent])
g_lua.registerMemberFunction("load", &lua_UI_load);
// UI.getRootContainer()
g_lua.registerMemberFunction("getRootContainer", &lua_UI_getRootContainer);
////////////////////////////////////////////////////////////////////////////////
// UIElement
g_lua.registerClass("UIElement");
// (UIElement) UIElement.new([UIContainer parent], [string id])
g_lua.registerMemberFunction("new", &lua_UIElement_new);
// (string) UIElement.id
g_lua.registerMemberField("id", &lua_UIElement_getId, &lua_UIElement_setId);
// (boolean) UIElement.enabled
g_lua.registerMemberField("enabled", &lua_UIElement_isEnabled, &lua_UIElement_setEnabled);
// (boolean UIElement.visible
g_lua.registerMemberField("visible", &lua_UIElement_isVisible, &lua_UIElement_setVisible);
// (boolean UIElement.focused
g_lua.registerMemberField("focused", &lua_UIElement_isFocused, &lua_UIElement_setFocused);
// (integer) UIElement.width
g_lua.registerMemberField("width", &lua_UIElement_getWidth, &lua_UIElement_setWidth);
// (integer) UIElement.height
g_lua.registerMemberField("height", &lua_UIElement_getHeight, &lua_UIElement_setHeight);
// (UIContainer UIElement.parent
g_lua.registerMemberField("parent", &lua_UIElement_getParent, &lua_UIElement_setParent);
// element:setLocked(boolean locked)
g_lua.registerMemberFunction("setLocked", &lua_UIElement_setLocked);
// element:setMargin(int all)
// element:setMargin(int vertical, int horizontal)
// element:setMargin(int top, right, bottom, left)
g_lua.registerMemberFunction("setMargin", &lua_UIElement_setMargin);
// element:destroy()
g_lua.registerMemberFunction("destroy", &lua_UIElement_destroy);
// element:centerIn(UIContainer target)
g_lua.registerMemberFunction("centerIn", &lua_UIElement_centerIn);
// element:addAnchor(AnchorPoint anchoredEdge, UIElement target, AnchorPoint targetEdge)
// element:addAnchor(AnchorPoint anchoredEdge, string targetId, AnchorPoint targetEdge)
g_lua.registerMemberFunction("addAnchor", &lua_UIElement_addAnchor);
////////////////////////////////////////////////////////////////////////////////
// UIContainer
g_lua.registerClass("UIContainer", "UIElement");
// UIContainer.new([UIContainer parent], [string id])
g_lua.registerMemberFunction("new", &lua_UIContainer_new);
// container:child(string id)
g_lua.registerMemberFunction("child", &lua_UIContainer_child);
// (table) container:children()
g_lua.registerMemberFunction("children", &lua_UIContainer_getChildren);
// container:addChild(UIElement child)
g_lua.registerMemberFunction("addChild", &lua_UIContainer_addChild);
////////////////////////////////////////////////////////////////////////////////
// UILabel
g_lua.registerClass("UILabel", "UIElement");
// UILabel.new([UIContainer parent], [string id])
g_lua.registerMemberFunction("new", &lua_UILabel_new);
// label.text
g_lua.registerMemberField("text", &lua_UILabel_getText, &lua_UILabel_setText);
////////////////////////////////////////////////////////////////////////////////
// UIButton
g_lua.registerClass("UIButton", "UIElement");
// UIButton.new([UIContainer parent], [string id])
g_lua.registerMemberFunction("new", &lua_UIButton_new);
// button.text
g_lua.registerMemberField("text", &lua_UIButton_getText, &lua_UIButton_setText);
////////////////////////////////////////////////////////////////////////////////
// UITextEdit
g_lua.registerClass("UITextEdit", "UIElement");
// UITextEdit.new([UIContainer parent], [string id])
g_lua.registerMemberFunction("new", &lua_UITextEdit_new);
// textEdit.text
g_lua.registerMemberField("text", &lua_UITextEdit_getText, &lua_UITextEdit_setText);
////////////////////////////////////////////////////////////////////////////////
// UIWindow
g_lua.registerClass("UIWindow", "UIContainer");
// UIWindow.new([UIContainer parent], [string id])
g_lua.registerMemberFunction("new", &lua_UIWindow_new);
// window.title
g_lua.registerMemberField("title", &lua_UIWindow_getTitle, &lua_UIWindow_setTitle);
////////////////////////////////////////////////////////////////////////////////
// Protocol
g_lua.registerClass("ProtocolLogin");
g_lua.registerMemberFunction("new", []{
g_lua.pushClassInstance(ScriptObjectPtr(new ProtocolLogin));
return 1;
});
g_lua.registerMemberFunction("login", []{
std::string accountPassword = g_lua.popString();
std::string accountName = g_lua.popString();
if(ProtocolLoginPtr protocolLogin = boost::dynamic_pointer_cast<ProtocolLogin>(g_lua.popClassInstance()))
protocolLogin->login(accountName, accountPassword);
return 0;
});
g_lua.registerMemberFunction("cancel", []{
//TODO: this func
return 0;
});
}

@ -7,46 +7,4 @@
void registerScriptFunctions();
// App
int lua_App_exit();
// UI
int lua_UI_load();
int lua_UI_getRootContainer();
// UIElement
int lua_UIElement_getId();
int lua_UIElement_setId();
int lua_UIElement_isEnabled();
int lua_UIElement_setEnabled();
int lua_UIElement_isVisible();
int lua_UIElement_setVisible();
int lua_UIElement_isFocused();
int lua_UIElement_setFocused();
int lua_UIElement_getParent();
int lua_UIElement_setParent();
int lua_UIElement_setLocked();
int lua_UIElement_destroy();
void lua_UIElement_onLoad();
void lua_UIElement_onDestroy();
// UIContainer
int lua_UIContainer_getChild();
int lua_UIContainer_getChildren();
// UILabel
int lua_UILabel_setText();
int lua_UILabel_getText();
// UITextEdit
int lua_UITextEdit_setText();
int lua_UITextEdit_getText();
// UIButton
void lua_UIButton_onClick();
// UIWindow
int lua_UIWindow_setTitle();
int lua_UIWindow_getTitle();
#endif // SCRIPTFUNCTIONS_H

@ -1,39 +1,12 @@
/* 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 UI_H
#define UI_H
#include <global.h>
#include <ui/uiconstants.h>
#include <ui/uiskins.h>
#include <ui/uiloader.h>
#include <ui/uielement.h>
#include <ui/uielementskin.h>
#include <ui/uicontainer.h>
#include <ui/uibutton.h>
#include <ui/uilabel.h>

@ -1,5 +1,6 @@
#include <global.h>
#include <ui/uianchorlayout.h>
#include <ui/uielement.h>
UIElementPtr Anchor::getAnchorLineElement() const
{
@ -13,17 +14,17 @@ int Anchor::getAnchorLinePoint() const
UIElementPtr anchorLineElement = getAnchorLineElement();
if(anchorLineElement) {
switch(m_anchorLine.getEdge()) {
case UI::AnchorLeft:
case AnchorLeft:
return anchorLineElement->getRect().left();
case UI::AnchorRight:
case AnchorRight:
return anchorLineElement->getRect().right();
case UI::AnchorTop:
case AnchorTop:
return anchorLineElement->getRect().top();
case UI::AnchorBottom:
case AnchorBottom:
return anchorLineElement->getRect().bottom();
case UI::AnchorHorizontalCenter:
case AnchorHorizontalCenter:
return anchorLineElement->getRect().horizontalCenter();
case UI::AnchorVerticalCenter:
case AnchorVerticalCenter:
return anchorLineElement->getRect().verticalCenter();
default:
break;
@ -31,7 +32,7 @@ int Anchor::getAnchorLinePoint() const
}
return -9999;
}
bool UIAnchorLayout::addAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
bool UIAnchorLayout::addAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
{
Anchor anchor(anchoredElement, anchoredEdge, anchorLine);
UIElementPtr anchorLineElement = anchor.getAnchorLineElement();
@ -71,36 +72,36 @@ void UIAnchorLayout::recalculateElementLayout(const UIElementPtr& element)
if(anchor.getAnchoredElement() == element && anchor.getAnchorLineElement()) {
int point = anchor.getAnchorLinePoint();
switch(anchor.getAnchoredEdge()) {
case UI::AnchorHorizontalCenter:
case AnchorHorizontalCenter:
rect.moveHorizontalCenter(point + element->getMarginLeft() - element->getMarginRight());
horizontalMoved = true;
break;
case UI::AnchorLeft:
case AnchorLeft:
if(!horizontalMoved) {
rect.moveLeft(point + element->getMarginLeft());
horizontalMoved = true;
} else
rect.setLeft(point + element->getMarginLeft());
break;
case UI::AnchorRight:
case AnchorRight:
if(!horizontalMoved) {
rect.moveRight(point - element->getMarginRight());
horizontalMoved = true;
} else
rect.setRight(point - element->getMarginRight());
break;
case UI::AnchorVerticalCenter:
case AnchorVerticalCenter:
rect.moveVerticalCenter(point + element->getMarginTop() - element->getMarginBottom());
verticalMoved = true;
break;
case UI::AnchorTop:
case AnchorTop:
if(!verticalMoved) {
rect.moveTop(point + element->getMarginTop());
verticalMoved = true;
} else
rect.setTop(point + element->getMarginTop());
break;
case UI::AnchorBottom:
case AnchorBottom:
if(!verticalMoved) {
rect.moveBottom(point - element->getMarginBottom());
verticalMoved = true;
@ -139,19 +140,19 @@ bool UIAnchorLayout::hasElementInAnchorTree(const UIElementPtr& element, const U
return false;
}
UI::AnchorPoint UIAnchorLayout::parseAnchorPoint(const std::string& anchorPointStr)
AnchorPoint UIAnchorLayout::parseAnchorPoint(const std::string& anchorPointStr)
{
if(anchorPointStr == "left")
return UI::AnchorLeft;
return AnchorLeft;
else if(anchorPointStr == "right")
return UI::AnchorRight;
return AnchorRight;
else if(anchorPointStr == "top")
return UI::AnchorTop;
return AnchorTop;
else if(anchorPointStr == "bottom")
return UI::AnchorBottom;
return AnchorBottom;
else if(anchorPointStr == "horizontalCenter")
return UI::AnchorHorizontalCenter;
return AnchorHorizontalCenter;
else if(anchorPointStr == "verticalCenter")
return UI::AnchorVerticalCenter;
return UI::AnchorNone;
return AnchorVerticalCenter;
return AnchorNone;
}

@ -2,48 +2,60 @@
#define UIANCHORLAYOUT_H
#include <global.h>
#include <ui/uiconstants.h>
#include <ui/uilayout.h>
#include <ui/uielement.h>
class UIElement;
typedef boost::shared_ptr<UIElement> UIElementPtr;
typedef boost::weak_ptr<UIElement> UIElementWeakPtr;
enum AnchorPoint {
AnchorNone = 0,
AnchorTop,
AnchorBottom,
AnchorLeft,
AnchorRight,
AnchorVerticalCenter,
AnchorHorizontalCenter,
};
class AnchorLine
{
public:
AnchorLine(const std::string& elementId, UI::AnchorPoint edge) : m_elementId(elementId), m_edge(edge) { }
AnchorLine(const std::string& elementId, AnchorPoint edge) : m_elementId(elementId), m_edge(edge) { }
AnchorLine(const AnchorLine& other) : m_elementId(other.m_elementId), m_edge(other.m_edge) { }
UI::AnchorPoint getEdge() const { return m_edge; }
AnchorPoint getEdge() const { return m_edge; }
const std::string& getElementId() const { return m_elementId; }
private:
std::string m_elementId;
UI::AnchorPoint m_edge;
AnchorPoint m_edge;
};
class Anchor
{
public:
Anchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
Anchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
: m_anchoredElement(anchoredElement), m_anchoredEdge(anchoredEdge), m_anchorLine(anchorLine) { }
UIElementPtr getAnchorLineElement() const ;
UIElementPtr getAnchoredElement() const { return m_anchoredElement.lock(); }
UI::AnchorPoint getAnchoredEdge() const { return m_anchoredEdge; }
AnchorPoint getAnchoredEdge() const { return m_anchoredEdge; }
int getAnchorLinePoint() const;
private:
UIElementWeakPtr m_anchoredElement;
UI::AnchorPoint m_anchoredEdge;
AnchorPoint m_anchoredEdge;
AnchorLine m_anchorLine;
};
class UIAnchorLayout : public UILayout
{
public:
bool addAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine);
bool addAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine);
void recalculateElementLayout(const UIElementPtr& element);
void recalculateChildrenLayout(const UIElementPtr& parent);
bool hasElementInAnchorTree(const UIElementPtr& element, const UIElementPtr& treeAnchor);
static UI::AnchorPoint parseAnchorPoint(const std::string& anchorPointStr);
static AnchorPoint parseAnchorPoint(const std::string& anchorPointStr);
private:
std::vector<Anchor> m_anchors;

@ -2,7 +2,6 @@
#define UIBUTTONSKIN_H
#include <global.h>
#include <ui/uiconstants.h>
#include <ui/uielementskin.h>
class Font;

@ -1,28 +0,0 @@
#ifndef UICONSTANTS_H
#define UICONSTANTS_H
namespace UI {
enum ElementType {
Element = 0,
Container,
Panel,
Window,
Label,
TextEdit,
Button,
CheckBox,
LineDecoration
};
enum AnchorPoint {
AnchorNone = 0,
AnchorTop,
AnchorBottom,
AnchorLeft,
AnchorRight,
AnchorVerticalCenter,
AnchorHorizontalCenter,
};
}
#endif // UICONSTANTS_H

@ -34,7 +34,7 @@ public:
const std::list<UIElementPtr>& getChildren() const { return m_children; }
/// Pushs a child to the top
void pushChildToTop(const UIElementPtr& child);
/// Return number of children
int getChildCount() const { return m_children.size(); }
/// Disable all children except the specified element

@ -5,6 +5,7 @@
#include <ui/uiskins.h>
#include <ui/uielementskin.h>
#include <ui/uicontainer.h>
#include <ui/uianchorlayout.h>
UIElement::UIElement(UI::ElementType type) :
ScriptObject(),
@ -17,7 +18,9 @@ UIElement::UIElement(UI::ElementType type) :
m_marginTop(0),
m_marginBottom(0)
{
// generate an unique id, this is need because anchoed layouts find elements by id
static unsigned long id = 1;
m_id = make_string("element", id++);
}
UIElement::~UIElement()
@ -62,12 +65,11 @@ void UIElement::destroyCheck()
void UIElement::setSize(const Size& size)
{
Rect rect = getRect();
if(rect.isValid())
rect.setSize(size);
else
rect = Rect(0, 0, size);
rect.setSize(size);
setRect(rect);
getLayout()->recalculateElementLayout(asUIElement());
if(UILayoutPtr layout = getLayout())
layout->recalculateElementLayout(asUIElement());
}
void UIElement::setRect(const Rect& rect)
@ -76,12 +78,18 @@ void UIElement::setRect(const Rect& rect)
m_rect = rect;
// rect updated, recalculate children layout
getLayout()->recalculateChildrenLayout(asUIElement());
if(UILayoutPtr layout = getLayout())
layout->recalculateChildrenLayout(asUIElement());
onRectUpdate();
}
}
void UIElement::applyDefaultSkin()
{
setSkin(g_uiSkins.getElementSkin(getElementType(), "default"));
}
void UIElement::setSkin(const UIElementSkinPtr& skin)
{
m_skin = skin;
@ -186,3 +194,20 @@ UILayoutPtr UIElement::getLayout() const
return getParent()->getLayout();
return UILayoutPtr();
}
void UIElement::centerIn(const std::string& targetId)
{
addAnchor(AnchorHorizontalCenter, AnchorLine(targetId, AnchorHorizontalCenter));
addAnchor(AnchorVerticalCenter, AnchorLine(targetId, AnchorVerticalCenter));
}
void UIElement::addAnchor(AnchorPoint anchoredEdge, AnchorLine anchorEdge)
{
UIElementPtr target = backwardsGetElementById(anchorEdge.getElementId());
if(!target)
warning("warning: element id '", anchorEdge.getElementId(), "' doesn't exist while anchoring element '", getId(), "'");
UIAnchorLayoutPtr layout = boost::dynamic_pointer_cast<UIAnchorLayout>(getLayout());
if(layout)
layout->addAnchor(asUIElement(), anchoredEdge, anchorEdge);
}

@ -4,11 +4,24 @@
#include <global.h>
#include <core/input.h>
#include <script/scriptobject.h>
#include <ui/uiconstants.h>
#include <ui/uielementskin.h>
#include <ui/uilayout.h>
#include <ui/uianchorlayout.h>
namespace UI {
enum ElementType {
Element = 0,
Container,
Panel,
Window,
Label,
TextEdit,
Button,
CheckBox,
LineDecoration
};
}
class UIElementSkin;
typedef boost::shared_ptr<UIElementSkin> UIElementSkinPtr;
class UIContainer;
typedef boost::shared_ptr<UIContainer> UIContainerPtr;
@ -44,6 +57,7 @@ public:
void setLayout(const UILayoutPtr& layout) { m_layout = layout; }
UILayoutPtr getLayout() const;
void applyDefaultSkin();
void setSkin(const UIElementSkinPtr& skin);
UIElementSkinPtr getSkin() const { return m_skin; }
@ -73,7 +87,14 @@ public:
virtual const char *getScriptObjectType() const { return "UIElement"; }
void setSize(const Size& size);
Size getSize() { return m_rect.size(); }
void setSize(int width, int height) { setSize(Size(width, height)); }
Size getSize() const { return m_rect.size(); }
void setWidth(int width) { setSize(width, getSize().height()); }
int getWidth() const { return getSize().width(); }
void setHeight(int height) { setSize(getSize().width(), height); }
int getHeight() const { return getSize().height(); }
/// Set the layout rect, always absolute position
void setRect(const Rect& rect);
@ -81,8 +102,8 @@ public:
Rect getRect() const { return m_rect; }
// margins
void setMargin(int top, int left, int bottom, int right) { m_marginLeft = left; m_marginRight = right; m_marginTop = top; m_marginBottom = bottom; getLayout()->recalculateElementLayout(asUIElement()); }
void setMargin(int horizontal, int vertical) { m_marginLeft = m_marginRight = horizontal; m_marginTop = m_marginBottom = vertical; getLayout()->recalculateElementLayout(asUIElement()); }
void setMargin(int top, int right, int bottom, int left) { m_marginLeft = left; m_marginRight = right; m_marginTop = top; m_marginBottom = bottom; getLayout()->recalculateElementLayout(asUIElement()); }
void setMargin(int vertical, int horizontal) { m_marginLeft = m_marginRight = horizontal; m_marginTop = m_marginBottom = vertical; getLayout()->recalculateElementLayout(asUIElement()); }
void setMargin(int margin) { m_marginLeft = m_marginRight = m_marginTop = m_marginBottom = margin; getLayout()->recalculateElementLayout(asUIElement()); }
void setMarginLeft(int margin) { m_marginLeft = margin; getLayout()->recalculateElementLayout(asUIElement()); }
void setMarginRight(int margin) { m_marginRight = margin; getLayout()->recalculateElementLayout(asUIElement()); }
@ -94,6 +115,10 @@ public:
int getMarginTop() const { return m_marginTop; }
int getMarginBottom() const { return m_marginBottom; }
// layout related
void centerIn(const std::string& targetId);
void addAnchor(AnchorPoint anchoredEdge, AnchorLine anchorEdge);
private:
UI::ElementType m_type;
UIContainerWeakPtr m_parent;

@ -3,12 +3,10 @@
#include <global.h>
#include <graphics/image.h>
#include <ui/uiconstants.h>
#include <ui/uielement.h>
#include <graphics/font.h>
#include <otml/otmlnode.h>
class UIElement;
class UIElementSkin
{
public:

@ -1,9 +1,11 @@
#include <global.h>
#include <ui/uilabel.h>
#include <ui/uielementskin.h>
void UILabel::setText(const std::string& text)
{
m_text = text;
// text size changed, reaplly skin
getSkin()->apply(this);
if(getSkin())
getSkin()->apply(this);
}

@ -13,7 +13,7 @@ public:
m_align(AlignLeftCenter) { }
void setText(const std::string& text);
std::string getText() const { return m_text; }
std::string getText() const { return m_text; }
void setAlign(AlignmentFlag align) { m_align = align; }
AlignmentFlag getAlign() const { return m_align; }

@ -48,11 +48,11 @@ UIElementPtr UILoader::createElementFromId(const std::string& id)
UIElementPtr UILoader::loadFromFile(std::string filePath, const UIContainerPtr& parent)
{
UIElementPtr element;
std::stringstream fin;
if(!g_resources.loadFile(filePath, fin)) {
error("ERROR: Could not load ui ", filePath);
return UIElementPtr();
}
if(!g_resources.loadFile(filePath, fin))
return element;
try {
OTMLParser parser(fin, filePath);
@ -65,7 +65,7 @@ UIElementPtr UILoader::loadFromFile(std::string filePath, const UIContainerPtr&
// only after that we can load anchors
// create element interpreting it's id
UIElementPtr element = createElementFromId(elementId);
element = createElementFromId(elementId);
if(!element) {
error(doc->front()->generateErrorMessage("invalid root element type"));
return element;
@ -81,12 +81,11 @@ UIElementPtr UILoader::loadFromFile(std::string filePath, const UIContainerPtr&
// report onLoad events
element->onLoad();
return element;
} catch(OTMLException e) {
error("ERROR: Failed to load ui ",filePath,": ", e.what());
}
return UIElementPtr();
return element;
}
void UILoader::populateContainer(const UIContainerPtr& parent, OTMLNode* node)
@ -138,7 +137,7 @@ void UILoader::loadElement(const UIElementPtr& element, OTMLNode* node)
element->setSkin(skin);
}
} else // apply default skin
element->setSkin(g_uiSkins.getElementSkin(element->getElementType(), "default"));
element->applyDefaultSkin();
// load elements common proprieties
if(node->hasChild("size"))
@ -151,12 +150,12 @@ void UILoader::loadElement(const UIElementPtr& element, OTMLNode* node)
element->setMarginBottom(node->readAtPath("margin/bottom", 0));
// load anchors
loadElementAnchor(element, UI::AnchorLeft, node->atPath("anchors/left"));
loadElementAnchor(element, UI::AnchorRight, node->atPath("anchors/right"));
loadElementAnchor(element, UI::AnchorTop, node->atPath("anchors/top"));
loadElementAnchor(element, UI::AnchorBottom, node->atPath("anchors/bottom"));
loadElementAnchor(element, UI::AnchorHorizontalCenter, node->atPath("anchors/horizontalCenter"));
loadElementAnchor(element, UI::AnchorVerticalCenter, node->atPath("anchors/verticalCenter"));
loadElementAnchor(element, AnchorLeft, node->atPath("anchors/left"));
loadElementAnchor(element, AnchorRight, node->atPath("anchors/right"));
loadElementAnchor(element, AnchorTop, node->atPath("anchors/top"));
loadElementAnchor(element, AnchorBottom, node->atPath("anchors/bottom"));
loadElementAnchor(element, AnchorHorizontalCenter, node->atPath("anchors/horizontalCenter"));
loadElementAnchor(element, AnchorVerticalCenter, node->atPath("anchors/verticalCenter"));
// load basic element events
loadElementScriptFunction(element, node->at("onLoad"));
@ -178,7 +177,7 @@ void UILoader::loadElement(const UIElementPtr& element, OTMLNode* node)
}
}
void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, OTMLNode* node)
void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, OTMLNode* node)
{
if(!node)
return;
@ -203,9 +202,9 @@ void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, UI::Anchor
}
std::string anchorLineElementId = split[0];
UI::AnchorPoint anchorLineEdge = UIAnchorLayout::parseAnchorPoint(split[1]);
AnchorPoint anchorLineEdge = UIAnchorLayout::parseAnchorPoint(split[1]);
if(anchorLineEdge == UI::AnchorNone) {
if(anchorLineEdge == AnchorNone) {
error(node->generateErrorMessage("invalid anchor type"));
return;
}

@ -26,11 +26,11 @@
#define UILOADER_H
#include <global.h>
#include <ui/uiconstants.h>
#include <ui/uicontainer.h>
#include <ui/uibutton.h>
#include <ui/uiwindow.h>
#include <ui/uilabel.h>
#include <ui/uianchorlayout.h>
class UILoader
{
@ -52,7 +52,7 @@ private:
void loadElement(const UIElementPtr& element, OTMLNode* node);
/// Load anchor from a OTML node
void loadElementAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, OTMLNode* node);
void loadElementAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, OTMLNode* node);
/// Load element lua function
void loadElementScriptFunction(const UIElementPtr& element, OTMLNode* node);

@ -41,7 +41,8 @@ public:
inline T width() const { return x2 - x1 + 1; }
inline T height() const { return y2 - y1 + 1; }
inline TSize<T> size() const { return TSize<T>(width(), height()); }
inline void clear() { x1 = y1 = 0; x2 = y2 = -1; }
inline void reset() { x1 = y1 = 0; x2 = y2 = -1; }
inline void clear() { x2 = x1 - 1; y2 = y1 - 1; }
inline void setLeft(T pos) { x1 = pos; }
inline void setTop(T pos) { y1 = pos; }
@ -178,48 +179,11 @@ public:
}
inline TRect<T> united(const TRect<T> &r) const {
if(isNull() || r.isNull())
return TRect<T>();
int l1 = x1;
int r1 = x1;
if (x2 - x1 + 1 < 0)
l1 = x2;
else
r1 = x2;
int l2 = r.x1;
int r2 = r.x1;
if(r.x2 - r.x1 + 1 < 0)
l2 = r.x2;
else
r2 = r.x2;
if(l1 > r2 || l2 > r1)
return TRect<T>();
int t1 = y1;
int b1 = y1;
if(y2 - y1 + 1 < 0)
t1 = y2;
else
b1 = y2;
int t2 = r.y1;
int b2 = r.y1;
if(r.y2 - r.y1 + 1 < 0)
t2 = r.y2;
else
b2 = r.y2;
if(t1 > b2 || t2 > b1)
return TRect<T>();
TRect<T> tmp;
tmp.x1 = std::max(l1, l2);
tmp.x2 = std::min(r1, r2);
tmp.y1 = std::max(t1, t2);
tmp.y2 = std::min(b1, b2);
tmp.x1 = std::min(x1, r.x1);
tmp.x2 = std::max(x2, r.x2);
tmp.y1 = std::min(y1, r.y1);
tmp.y2 = std::max(y2, r.y2);
return tmp;
}
@ -269,6 +233,9 @@ public:
inline bool operator==(const TRect<T>& other) const { return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2); }
inline bool operator!=(const TRect<T>& other) const { return (x1 != other.x1 || y1 != other.y1 || x2 != other.x2 || y2 != other.y2); }
inline TRect<T>& operator|=(const TRect<T>& other) { *this = united(other); return *this; }
inline TRect<T>& operator&=(const TRect<T>& other) { *this = intersection(other); return *this; }
private:
T x1, y1, x2, y2;
};

@ -116,7 +116,7 @@ int main(int argc, const char *argv[])
g_engine.enableFpsCounter();
// load ui skins
g_uiSkins.load("tibia");
g_uiSkins.load("tibiaskin");
// load script modules
g_lua.loadAllModules();

@ -29,13 +29,20 @@
ProtocolLogin::ProtocolLogin()
{
trace();
}
ProtocolLogin::~ProtocolLogin()
{
trace();
}
void ProtocolLogin::login(const std::string& accountName, const std::string& accountPassword)
{
trace();
if(accountName.empty() || accountPassword.empty()) {
// shows error dialog
g_lua.pushString("You must enter an account name and password.");
callScriptTableField("onError", 1);
return;
}
@ -70,6 +77,7 @@ void ProtocolLogin::onConnect()
void ProtocolLogin::sendPacket()
{
trace();
OutputMessage oMsg;
oMsg.addU8(0x01); // Protocol id
@ -111,6 +119,7 @@ void ProtocolLogin::sendPacket()
void ProtocolLogin::onRecv(InputMessage *inputMessage)
{
trace();
Protocol::onRecv(inputMessage);
while(!inputMessage->end()) {
@ -132,6 +141,7 @@ void ProtocolLogin::onRecv(InputMessage *inputMessage)
void ProtocolLogin::parseError(InputMessage *inputMessage)
{
trace();
std::string error = inputMessage->getString();
g_lua.pushString(error);
callScriptTableField("onError", 1);
@ -139,6 +149,7 @@ void ProtocolLogin::parseError(InputMessage *inputMessage)
void ProtocolLogin::parseMOTD(InputMessage *inputMessage)
{
trace();
std::string motd = inputMessage->getString();
g_lua.pushString(motd);
callScriptTableField("onMotd", 1);
@ -146,6 +157,7 @@ void ProtocolLogin::parseMOTD(InputMessage *inputMessage)
void ProtocolLogin::parseCharacterList(InputMessage *inputMessage)
{
trace();
uint8 characters = inputMessage->getU8();
for(int i = 0; i < characters; ++i) {
std::string name = inputMessage->getString();

@ -1,27 +1,3 @@
/* 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 PROTOCOLLOGIN_H
#define PROTOCOLLOGIN_H
@ -31,6 +7,7 @@ class ProtocolLogin : public Protocol
{
public:
ProtocolLogin();
~ProtocolLogin();
void login(const std::string& accountName, const std::string& accountPassword);

Loading…
Cancel
Save