lua scripting

This commit is contained in:
Eduardo Bart 2011-04-21 19:44:30 -03:00
parent bb05338190
commit 50b99a75b9
27 changed files with 674 additions and 145 deletions

View File

@ -6,7 +6,7 @@ SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
# find needed packages
SET(Boost_USE_STATIC_LIBS ON)
SET(Boost_USE_MULTITHREADED ON)
FIND_PACKAGE(Boost COMPONENTS system regex REQUIRED)
FIND_PACKAGE(Boost COMPONENTS system regex signals REQUIRED)
FIND_PACKAGE(OpenGL REQUIRED)
FIND_PACKAGE(Lua51 REQUIRED)
FIND_PACKAGE(YamlCpp REQUIRED)
@ -52,7 +52,7 @@ IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
ADD_DEFINITIONS(-D_DEBUG)
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(SOURCES src/framework/script/script.cpp
SET(SOURCES
# game sources
src/main.cpp
src/menustate.cpp
@ -68,8 +68,8 @@ SET(SOURCES src/framework/script/script.cpp
src/framework/core/engine.cpp
# framework script
src/framework/script/script.cpp
src/framework/script/scriptfunctions.cpp
src/framework/script/luascript.cpp
src/framework/script/luafunctions.cpp
# framework utilities
src/framework/util/color.cpp

View File

View File

@ -1,22 +0,0 @@
MainMenuController = {}
enterGameController = {}
function enterGameController.enterGameButton_clicked()
createEnterGameWindow()
end
function mainMenuController.createMainMenu()
mainMenuPanel = loadUI("ui/mainMenuPanel.yml")
enterGameButton = mainMenuPanel:getElementById("enterGameButton")
enterGameButton.setOnClick(enterGameController.enterGameButton_clicked)
exitButton = mainMenuPanel:getElementById("exitButton")
exitButton:setOnClick(function() exitGame() end)
end
function onEnter()
mainMenuController:createMainMenu()
end
function onLeave()
end

View File

@ -49,6 +49,9 @@ window#enterGameWindow:
anchors.bottom: parent.bottom
margin.bottom: 10
margin.right: 13
onClick: |
enterGameWindow:destroy()
enterGameWindow = nil
textEdit#accountNameTextEdit:
anchors.right: parent.right

View File

@ -1 +0,0 @@
require("modules/mainmenu/mainmenu")

View File

@ -1 +1,23 @@
loadUI("modules/mainmenu/mainmenu.yml")
-- events
function MainMenu_enterGameClicked()
enterGameWindow = loadUI("modules/mainmenu/entergamewindow.yml")
end
function MainMenu_optionsClicked()
optionsWindow = loadUI("modules/mainmenu/optionswindow.yml")
end
function MainMenu_infoClicked()
infoWindow = loadUI("modules/mainmenu/infowindow.yml")
end
function MainMenu_exitClicked()
exitGame()
end
-- create main menu
function MainMenu_create()
menuPanel = loadUI("modules/mainmenu/mainmenu.yml")
end
MainMenu_create()

View File

@ -11,6 +11,7 @@ panel#mainMenu:
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 16
onClick: MainMenu_enterGameClicked()
button#accessAccountButton:
text: Access Account
@ -23,15 +24,18 @@ panel#mainMenu:
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 76
onClick: MainMenu_optionsClicked()
button#infoButton:
text: Info
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 106
onClick: MainMenu_infoClicked()
button#exitGameButton:
text: Exit
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 136
onClick: MainMenu_exitClicked()

View File

@ -109,3 +109,6 @@ window#optionsWindow:
anchors.bottom: parent.bottom
margin.right: 10
margin.bottom: 13
onClick: |
optionsWindow:destroy()
optionsWindow = nil

View File

@ -1,37 +0,0 @@
panel#mainMenu:
skin: roundedGridPanel
size: [117, 171]
anchors.left: parent.left
anchors.bottom: parent.bottom
margin.left: 60
margin.bottom: 70
button#enterGameButton:
text: Enter Game
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 16
button#accessAccountButton:
text: Access Account
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 46
button#optionsButton:
text: Options
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 76
button#infoButton:
text: Info
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 106
button#exitGameButton:
text: Exit
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin.top: 136

View File

@ -69,6 +69,7 @@ typedef int8_t int8;
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/signals.hpp>
#define foreach BOOST_FOREACH
typedef boost::function<void()> Callback;

View File

@ -0,0 +1,112 @@
/* 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 <prerequisites.h>
#include <script/luascript.h>
#include <core/engine.h>
#include <core/resources.h>
#include <ui/ui.h>
void LuaScript::registerFunctions()
{
registerGlobalFunction("exitGame", &LuaScript::lua_exitGame);
registerGlobalFunction("loadUI", &LuaScript::lua_loadUI);
registerGlobalFunction("getUIRootContainer", &LuaScript::lua_getUIRootContainer);
registerClass("UILayout");
registerClass("UIElement", "UILayout");
registerClass("UIButton", "UIElement");
registerClass("UITextEdit", "UIElement");
registerClass("UICheckBox", "UIElement");
registerClass("UIContainer", "UIElement");
registerClass("UIWindow", "UIContainer");
registerMemberFunction("UIElement", "destroy", &LuaScript::lua_UIElement_destroy);
registerMemberFunction("UIContainer", "getChildByID", &LuaScript::lua_UIContainer_getChildByID);
registerMemberFunction("UIButton", "setOnClick", &LuaScript::lua_UIButton_setOnClick);
}
int LuaScript::lua_exitGame()
{
g_engine.stop();
return 1;
}
int LuaScript::lua_loadUI()
{
UIContainerPtr parent;
if(getStackSize() > 1) {
parent = boost::static_pointer_cast<UIContainer>(popClassInstance());
} else {
parent = UIContainer::getRootContainer();
}
std::string uiFile = popString();
UIElementPtr element = UILoader::loadFile(uiFile.c_str(), parent);
pushClassInstance(element);
return 1;
}
int LuaScript::lua_getUIRootContainer()
{
UIContainerPtr rootContainer = UIContainer::getRootContainer();
pushClassInstance(rootContainer);
return 1;
}
int LuaScript::lua_UIElement_destroy()
{
UIElementPtr element = boost::static_pointer_cast<UIElement>(popClassInstance());
element->destroy();
return 1;
}
int LuaScript::lua_UIButton_setOnClick()
{
lua_insert(L, -2);
UIButtonPtr button = boost::static_pointer_cast<UIButton>(popClassInstance());
if(button) {
int funcRef = popFunction();
button->setOnClick([this, funcRef] {
pushFunction(funcRef);
callFunction();
});
} else {
pop();
}
return 1;
}
int LuaScript::lua_UIContainer_getChildByID()
{
std::string id = popString();
ScriptablePtr object = popClassInstance();
if(object && strcmp("UIContainer", object->getScriptableName()) == 0) {
UIContainerPtr container = boost::static_pointer_cast<UIContainer>(object);
pushClassInstance(container->getChildById(id));
} else {
pushNil();
}
return 1;
}

View File

@ -0,0 +1,344 @@
/* 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 <prerequisites.h>
#include <script/luascript.h>
#include <core/resources.h>
LuaScript g_lua;
LuaScript::LuaScript()
{
L = luaL_newstate();
if(!L)
logFatal("could not create lua context");
// load lua standard libraries
luaL_openlibs(L);
// setup custom package loader
setupPackageLoader();
// register classes and functions
registerFunctions();
}
LuaScript::~LuaScript()
{
lua_close(L);
}
bool LuaScript::loadFile(const std::string& fileName)
{
if(!g_resources.fileExists(fileName)) {
logError("lua script file '%s' doesn't exist", fileName.c_str());
return false;
}
std::string fileContents = g_resources.loadTextFile(fileName);
return loadBuffer(fileContents, fileName);
}
bool LuaScript::loadBuffer(const std::string& text, const std::string& what)
{
// load buffer
int ret = luaL_loadbuffer(L, text.c_str(), text.length(), what.c_str());
if(ret != 0){
logError((std::string("while parsing lua code: ") + popString()).c_str());
return false;
}
// check if that is loaded as a function
if(lua_isfunction(L, -1) == 0) {
logError("lua code not loaded as function");
return false;
}
// execute it
ret = lua_pcall(L, 0, 0, 0);
if(ret != 0){
logError((std::string("while loading lua code: ") + popString()).c_str());
return false;
}
return true;
}
int LuaScript::loadBufferAsFunction(const std::string& text, const std::string& what)
{
int ret = luaL_loadstring(L, text.c_str());
if(ret != 0){
logError((std::string("while parsing lua code: ") + popString()).c_str());
return LUA_REFNIL;
}
// check if that is loaded as a function
if(lua_isfunction(L, -1) == 0) {
logError("lua code not loaded as function");
return LUA_REFNIL;
}
return popFunction();
}
int LuaScript::getStackSize()
{
return lua_gettop(L);
}
void LuaScript::pop(int n)
{
lua_pop(L, n);
}
bool LuaScript::popBoolean()
{
bool b = (lua_toboolean(L, -1) != 0);
pop();
return b;
}
int32_t LuaScript::popInteger()
{
double d;
if(lua_istable(L, -1)) {
lua_getfield(L, -1, "__intValue");
d = lua_tonumber(L, -1);
pop(2);
}
else{
d = lua_tonumber(L, -1);
pop(1);
}
return (int)d;
}
std::string LuaScript::popString()
{
size_t len;
const char* cstr = lua_tolstring(L, -1, &len);
std::string str(cstr, len);
pop();
return str;
}
void LuaScript::pushNil()
{
lua_pushnil(L);
}
void LuaScript::pushBoolean(bool b)
{
lua_pushboolean(L, b);
}
void LuaScript::pushInteger(int32_t i)
{
lua_pushnumber(L, i);
}
void LuaScript::pushString(const std::string& str)
{
lua_pushstring(L, str.c_str());
}
void LuaScript::pushUserdata(void* ptr)
{
lua_pushlightuserdata(L, ptr);
}
void LuaScript::pushClassInstance(const ScriptablePtr& object)
{
if(object->getScriptableName()) {
new(lua_newuserdata(L, sizeof(ScriptableWeakPtr))) ScriptableWeakPtr(object);
lua_getfield(L, LUA_REGISTRYINDEX, (std::string(object->getScriptableName()) + "_mt").c_str());
lua_setmetatable(L, -2);
}
}
ScriptablePtr LuaScript::popClassInstance()
{
if(!lua_isuserdata(L, -1)) {
logError("Couldn't pop a class instance, top objet is not a valid type (%s)", luaL_typename(L, -1));
lua_pop(L, 1);
return ScriptablePtr();
}
ScriptableWeakPtr *objectRef = (ScriptableWeakPtr *)lua_touserdata(L, -1);
lua_pop(L, 1);
return objectRef->lock();
}
int LuaScript::popFunction()
{
return luaL_ref(L, LUA_REGISTRYINDEX);
}
void LuaScript::pushFunction(int functionRef)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, functionRef);
}
void LuaScript::callFunction(int numArgs, bool itReturnsValue)
{
lua_call(L, numArgs, itReturnsValue ? 1 : 0);
}
void LuaScript::setupPackageLoader()
{
lua_getfield(L, LUA_GLOBALSINDEX, "package");
lua_getfield(L, -1, "loaders");
lua_remove(L, -2);
lua_pushnil(L);
int numLoaders = 0;
while(lua_next(L, -2) != 0) {
lua_pop(L, 1);
numLoaders++;
}
lua_pushinteger(L, numLoaders + 1);
lua_pushcfunction(L, &LuaScript::luaPackageLoader);
lua_rawset(L, -3);
lua_pop(L, 1);
}
void LuaScript::registerClass(const std::string& klass, const std::string& baseClass)
{
// klass_mt = {}
lua_newtable(L); // klass metatable
lua_pushvalue(L, -1); // another reference to the metatable
lua_setfield(L, LUA_REGISTRYINDEX, (klass + "_mt").c_str()); // register the metatable at registry index
// set __gc metamethod, which collects userdata
lua_pushcfunction(L, &LuaScript::luaCollectClassInstance);
lua_setfield(L, -2, "__gc");
// set __eq metamethod
lua_pushcfunction(L, &LuaScript::luaCompareClassInstances);
lua_setfield(L, -2, "__eq");
// klass = {}
lua_newtable(L); // klass table
lua_pushvalue(L, -1); // another reference to the table
lua_setfield(L, LUA_GLOBALSINDEX, klass.c_str()); // register at globals index
// klass.className = "klass"
lua_pushstring(L, klass.c_str());
lua_setfield(L, -2, "className");
// klass_mt.__index = klass
lua_setfield(L, -2, "__index");
// pop the class metatable
lua_pop(L, 1);
if(baseClass.length() > 0) {
// add klass table to the top of the stack
lua_getfield(L, LUA_GLOBALSINDEX, klass.c_str());
// redirect = { __index = baseClass }
lua_newtable(L);
lua_getfield(L, LUA_GLOBALSINDEX, baseClass.c_str());
lua_setfield(L, -2, "__index");
// setmetatable(klass, redirect)
lua_setmetatable(L, -2);
// pop the derived class table
lua_pop(L, 1);
}
}
void LuaScript::registerMemberFunction(const std::string& klass, const std::string& functionName, LuaCFunction function)
{
int functionId = m_functions.size();
m_functions.push_back(function);
// push the class table
lua_getfield(L, LUA_GLOBALSINDEX, klass.c_str());
// push the function id
lua_pushnumber(L, functionId);
// store id in the closure
lua_pushcclosure(L, &LuaScript::luaFunctionCallback, 1);
// store the function at the class field functionName
lua_setfield(L, -2, functionName.c_str());
// pop the table
lua_pop(L, 1);
}
void LuaScript::registerGlobalFunction(const std::string& functionName, LuaCFunction function)
{
int functionId = m_functions.size();
m_functions.push_back(function);
// push the function id
lua_pushnumber(L, functionId);
// store id in the closure
lua_pushcclosure(L, &LuaScript::luaFunctionCallback, 1);
// store the function in the global lua table
lua_setfield(L, LUA_GLOBALSINDEX, functionName.c_str());
}
int LuaScript::luaPackageLoader(lua_State* L)
{
std::string fileName = lua_tostring(L, -1);
fileName += ".lua";
if(g_resources.fileExists(fileName)) {
std::string fileContents = g_resources.loadTextFile(fileName);
luaL_loadbuffer(L, fileContents.c_str(), fileContents.length(), fileName.c_str());
} else {
lua_pushfstring(L, "\n\tcould not load lua script " LUA_QS, fileName.c_str());
}
return 1;
}
int LuaScript::luaCollectClassInstance(lua_State* L)
{
ScriptableWeakPtr *objectRef = (ScriptableWeakPtr *)lua_touserdata(L, -1);
objectRef->reset();
lua_pop(L, 1);
return 1;
}
int LuaScript::luaCompareClassInstances(lua_State* L)
{
if(!lua_isuserdata(L, -1) || !lua_isuserdata(L, -2)) {
lua_pop(L, 2);
lua_pushboolean(L, 0);
} else {
ScriptableWeakPtr *objectRef1 = (ScriptableWeakPtr *)lua_touserdata(L, -1);
ScriptableWeakPtr *objectRef2 = (ScriptableWeakPtr *)lua_touserdata(L, -2);
lua_pop(L, 2);
if(objectRef1->lock() == objectRef2->lock())
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
}
return 1;
}
int LuaScript::luaFunctionCallback(lua_State* L)
{
int id = lua_tonumber(L, lua_upvalueindex(1));
return (g_lua.*(g_lua.m_functions[id]))();
}

View File

@ -0,0 +1,95 @@
/* 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 LUASCRIPT_H
#define LUASCRIPT_H
#include <prerequisites.h>
#include <script/scriptable.h>
#include <lua.hpp>
class LuaScript
{
public:
LuaScript();
virtual ~LuaScript();
bool loadFile(const std::string& fileName);
bool loadBuffer(const std::string& text, const std::string& what = "luaBuffer");
int loadBufferAsFunction(const std::string& text, const std::string& what = "luaBuffer");
int getStackSize();
void pushNil();
void pushBoolean(bool b);
void pushInteger(int i);
void pushString(const std::string& str);
void pushUserdata(void* ptr);
void pop(int n = 1);
bool popBoolean();
int32_t popInteger();
std::string popString();
int popFunction();
void pushFunction(int functionRef);
void callFunction(int numArgs = 0, bool itReturnsValue = false);
void pushClassInstance(const ScriptablePtr& object);
ScriptablePtr popClassInstance();
typedef int (LuaScript::*LuaCFunction)();
void setupPackageLoader();
void registerClass(const std::string& klass, const std::string& baseClass = "");
void registerMemberFunction(const std::string& klass, const std::string& functionName, LuaCFunction function);
void registerGlobalFunction(const std::string& functionName, LuaCFunction function);
static int luaFunctionCallback(lua_State* L);
static int luaPackageLoader(lua_State* L);
static int luaCollectClassInstance(lua_State* L);
static int luaCompareClassInstances(lua_State* L);
void registerFunctions();
int lua_UIButton_setOnClick();
int lua_UIElement_destroy();
// container functions
int lua_UIContainer_getChildByID();
// global functions
int lua_exitGame();
int lua_loadUI();
int lua_getUIRootContainer();
private:
std::vector<LuaCFunction> m_functions;
lua_State *L;
};
extern LuaScript g_lua;
#endif // LUASCRIPT_H

View File

@ -0,0 +1,39 @@
/* 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 SCRIPTABLE_H
#define SCRIPTABLE_H
#include <prerequisites.h>
class Scriptable : public boost::enable_shared_from_this<Scriptable>
{
public:
virtual const char *getScriptableName() const { return NULL; }
};
typedef boost::shared_ptr<Scriptable> ScriptablePtr;
typedef boost::weak_ptr<Scriptable> ScriptableWeakPtr;
#endif

View File

@ -45,6 +45,8 @@ public:
void setOnClick(const Callback& callback) { m_buttonClickCallback = callback; }
virtual const char *getScriptableName() const { return "UIButton"; }
private:
std::string m_text;
UI::EButtonState m_state;

View File

@ -30,9 +30,10 @@
class UICheckBox : public UIElement
{
public:
UICheckBox(UI::EElementType type = UI::Element);
virtual const char *getScriptableName() const { return "UICheckBox"; }
};
#endif // UICHECKBOX_H

View File

@ -62,6 +62,8 @@ public:
virtual UI::EElementType getElementType() const { return UI::Container; }
UIContainerPtr asUIContainer() { return boost::static_pointer_cast<UIContainer>(shared_from_this()); }
virtual const char *getScriptableName() const { return "UIContainer"; }
/// Get root container (the container that contains everything)
static UIContainerPtr& getRootContainer();

View File

@ -84,6 +84,7 @@ public:
UIElementPtr asUIElement() { return boost::static_pointer_cast<UIElement>(shared_from_this()); }
virtual UIContainerPtr asUIContainer() { return UIContainerPtr(); }
virtual const char *getScriptableName() const { return "UIElement"; }
friend class UIContainer;

View File

@ -43,6 +43,8 @@ public:
void setAlign(int align) { m_align = align; }
int getAlign() const { return m_align; }
virtual const char *getScriptableName() const { return "UILabel"; }
private:
std::string m_text;
int m_align;

View File

@ -27,6 +27,7 @@
#include <prerequisites.h>
#include <ui/uiconstants.h>
#include <script/scriptable.h>
enum EAnchorType {
ANCHOR_LEFT = 0,
@ -62,7 +63,7 @@ private:
EAnchorType m_anchorType;
};
class UILayout : public boost::enable_shared_from_this<UILayout>
class UILayout : public Scriptable
{
public:
UILayout() :
@ -106,7 +107,9 @@ public:
void setMarginTop(int margin) { m_marginTop = margin; recalculateLayout(); }
void setMarginBottom(int margin) { m_marginBottom = margin; recalculateLayout(); }
UILayoutPtr asUILayout() { return shared_from_this(); }
UILayoutPtr asUILayout() { return boost::static_pointer_cast<UILayout>(shared_from_this()); }
virtual const char *getScriptableName() const { return "UILayout"; }
protected:
virtual void onLayoutRectChange(const Rect& newRect) { }

View File

@ -26,6 +26,7 @@
#include <core/resources.h>
#include <ui/ui.h>
#include <ui/uiloader.h>
#include <script/luascript.h>
UIElementPtr UILoader::createElementFromId(const std::string& id)
{
@ -149,10 +150,8 @@ void UILoader::loadElements(const UIElementPtr& parent, const YAML::Node& node)
void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
{
// load specific element type
if(element->getElementType() == UI::Button) {
UIButtonPtr button = boost::static_pointer_cast<UIButton>(element);
button->setText(node["text"].Read<std::string>());
}
if(element->getElementType() == UI::Button)
loadButton(boost::static_pointer_cast<UIButton>(element), node);
else if(element->getElementType() == UI::Window) {
UIWindowPtr window = boost::static_pointer_cast<UIWindow>(element);
window->setTitle(node["title"].Read<std::string>());
@ -266,3 +265,18 @@ void UILoader::loadElementAnchor(const UIElementPtr& element, EAnchorType type,
throw YAML::Exception(node.GetMark(), "anchoring failed, does the relative element really exists?");
}
}
void UILoader::loadButton(const UIButtonPtr& button, const YAML::Node& node)
{
button->setText(node["text"].Read<std::string>());
// set on click event
if(node.FindValue("onClick")) {
int funcRef = g_lua.loadBufferAsFunction(node["onClick"].Read<std::string>());
if(funcRef != LUA_REFNIL) {
g_lua.pushClassInstance(button);
g_lua.pushFunction(funcRef);
g_lua.lua_UIButton_setOnClick();
}
}
}

View File

@ -28,6 +28,7 @@
#include <prerequisites.h>
#include <ui/uiconstants.h>
#include <ui/uicontainer.h>
#include <ui/uibutton.h>
class UILoader
{
@ -50,6 +51,9 @@ private:
/// Load anchor from a YAML node
static void loadElementAnchor(const UIElementPtr& element, EAnchorType type, const YAML::Node& node);
// specific elements loading
static void loadButton(const UIButtonPtr& button, const YAML::Node& node);
};
#endif // UILOADER_H

View File

@ -46,6 +46,8 @@ public:
bool isFocusable() const { return true; }
virtual const char *getScriptableName() const { return "UITextEdit"; }
private:
TextArea m_textArea;
};

View File

@ -40,6 +40,8 @@ public:
void setTitle(const std::string& title) { m_title = title; }
const std::string& getTitle() const { return m_title; }
virtual const char *getScriptableName() const { return "UIWindow"; }
private:
std::string m_title;
bool m_moving;

View File

@ -31,7 +31,7 @@
#include <ui/uiskins.h>
#include "menustate.h"
#include "teststate.h"
#include <script/script.h>
#include <script/luascript.h>
/// Catches signals so we can exit nicely
void signal_handler(int sig)
@ -110,8 +110,6 @@ int main(int argc, const char *argv[])
// init engine
g_engine.init();
g_script.init();
g_script.loadFile("lib/init.lua");
g_uiSkins.load("skins/tibiaskin.yml");
// state scope

View File

@ -32,29 +32,14 @@
#include <graphics/fonts.h>
#include <ui/ui.h>
#include "menustate.h"
#include <script/script.h>
#include <script/luascript.h>
void MenuState::onEnter()
{
m_background = g_textures.get("background.png");
m_background->enableBilinearFilter();
g_script.loadFile("modules/mainmenu/init.lua");
/*
UIContainerPtr mainMenuPanel = UILoader::loadFile("ui/mainMenu.yml")->asUIContainer();
UIButtonPtr button = boost::static_pointer_cast<UIButton>(mainMenuPanel->getChildById("exitGameButton"));
button->setOnClick(boost::bind(&MenuState::onClose, this));
button = boost::static_pointer_cast<UIButton>(mainMenuPanel->getChildById("enterGameButton"));
button->setOnClick(boost::bind(&MenuState::enterGameButton_clicked, this));
button = boost::static_pointer_cast<UIButton>(mainMenuPanel->getChildById("infoButton"));
button->setOnClick(boost::bind(&MenuState::infoButton_clicked, this));
button = boost::static_pointer_cast<UIButton>(mainMenuPanel->getChildById("optionsButton"));
button->setOnClick(boost::bind(&MenuState::optionsButton_clicked, this));
*/
g_lua.loadFile("modules/mainmenu/mainmenu.lua");
}
void MenuState::onLeave()
@ -92,53 +77,3 @@ void MenuState::render()
g_graphics.drawTexturedRect(Rect(0, 0, screenSize), m_background, texCoords);
}
void MenuState::enterGameButton_clicked()
{
UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UILoader::loadFile("ui/enterGameWindow.yml"));
window->getParent()->lockElement(window);
UIButtonPtr button = boost::static_pointer_cast<UIButton>(window->getChildById("cancelButton"));
button->setOnClick([] {
UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UIContainer::getRootContainer()->getChildById("enterGameWindow"));
window->getParent()->unlockElement();
window->destroy();
});
button = boost::static_pointer_cast<UIButton>(window->getChildById("okButton"));
button->setOnClick(boost::bind(&MenuState::enterGameWindowOkButton_clicked, this));
}
void MenuState::infoButton_clicked()
{
UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UILoader::loadFile("ui/infoWindow.yml"));
window->getParent()->lockElement(window);
UIButtonPtr button = boost::static_pointer_cast<UIButton>(window->getChildById("okButton"));
button->setOnClick([] {
UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UIContainer::getRootContainer()->getChildById("infoWindow"));
window->getParent()->unlockElement();
window->destroy();
});
}
void MenuState::enterGameWindowOkButton_clicked()
{
UIContainerPtr enterGameWindow = boost::static_pointer_cast<UIContainer>(UIContainer::getRootContainer()->getChildById("enterGameWindow"));
std::string accountName = boost::static_pointer_cast<UITextEdit>(enterGameWindow->getChildById("accountNameTextEdit"))->getText();
std::string password = boost::static_pointer_cast<UITextEdit>(enterGameWindow->getChildById("passwordTextEdit"))->getText();
//m_protocolLogin = ProtocolLoginPtr(new ProtocolLogin);
//m_protocolLogin->login(accountName, password);
}
void MenuState::optionsButton_clicked()
{
UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UILoader::loadFile("ui/optionsWindow.yml"));
window->getParent()->lockElement(window);
UIButtonPtr button = boost::static_pointer_cast<UIButton>(window->getChildById("okButton"));
button->setOnClick([] {
UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UIContainer::getRootContainer()->getChildById("optionsWindow"));
window->getParent()->unlockElement();
window->destroy();
});
}