lua scripting
This commit is contained in:
parent
bb05338190
commit
50b99a75b9
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
require("modules/mainmenu/mainmenu")
|
|
@ -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()
|
|
@ -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()
|
|
@ -109,3 +109,6 @@ window#optionsWindow:
|
|||
anchors.bottom: parent.bottom
|
||||
margin.right: 10
|
||||
margin.bottom: 13
|
||||
onClick: |
|
||||
optionsWindow:destroy()
|
||||
optionsWindow = nil
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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]))();
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) { }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -46,6 +46,8 @@ public:
|
|||
|
||||
bool isFocusable() const { return true; }
|
||||
|
||||
virtual const char *getScriptableName() const { return "UITextEdit"; }
|
||||
|
||||
private:
|
||||
TextArea m_textArea;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue