scripting rework

master
Eduardo Bart 13 years ago
parent f290b4f89c
commit c052723477

@ -16,6 +16,6 @@ end
-- here is where everything starts
if not initialStateLoaded then
onEnterMenuState()
App.setOnClose(onApplicationClose)
App.onClose = onApplicationClose
initialStateLoaded = true
end

@ -1,9 +1,11 @@
function autoDestroyParent()
self.parent:destroy()
end
function messageBox(title, text)
local msgbox = UI.load("modules/messagebox/messagebox.yml")
local label = msgbox:getChildById("messageBoxLabel")
local okButton = msgbox:getChildById("messageBoxOkButton")
msgbox.locked = true
msgbox.title = title
label.text = text
okButton.onClick = function() msgbox:destroy() end
local msgBox = UI.load("modules/messagebox/messagebox.yml")
msgBox.locked = true
msgBox.title = title
msgBox:child("textLabel").text = text
msgBox:child("okButton").onClick = autoDestroyParent
end

@ -4,12 +4,12 @@ window#messageBoxWindow:
anchors.verticalCenter: parent.verticalCenter
label#messageBoxLabel:
label#textLabel:
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
margin.top: 27
button#messageBoxOkButton:
button#okButton:
text: Ok
size: [43, 20]
anchors.right: parent.right

@ -44,7 +44,7 @@ public:
void setValue(const std::string &key, bool value);
void setValue(const std::string &key, int value);
const std::string &getString(const std::string &key) const;
const std::string& getString(const std::string &key) const;
float getFloat(const std::string &key) const;
bool getBoolean(const std::string &key) const;
int getInteger(const std::string &key) const;

@ -30,6 +30,7 @@
#include <graphics/fonts.h>
#include <ui/uicontainer.h>
#include <net/connection.h>
#include <script/luascript.h>
Engine g_engine;
@ -116,10 +117,12 @@ void Engine::run()
m_stopping = false;
m_running = false;
g_lua.collectGarbage();
// destroy root ui
rootContainer->destroy();
// poll remaning ui events
// poll remaning events
g_engine.poll();
}
@ -130,8 +133,7 @@ void Engine::stop()
void Engine::onClose()
{
if(m_onCloseCallback)
g_dispatcher.addTask(m_onCloseCallback);
g_dispatcher.addTask(boost::bind(&LuaScript::callModuleField, &g_lua, "App", "onClose"));
}
void Engine::onResize(const Size& size)

@ -63,16 +63,12 @@ public:
/// Return the current ticks on this frame
int getCurrentFrameTicks() const { return m_lastFrameTicks; }
void setOnClose(SimpleCallback onCloseCallback) { m_onCloseCallback = onCloseCallback; }
private:
bool m_stopping;
bool m_running;
bool m_calculateFps;
int m_lastFrameTicks;
SimpleCallback m_onCloseCallback;
};
extern Engine g_engine;

@ -53,7 +53,7 @@ public:
void appendCharacter(char c);
void removeCharacter(bool right);
const std::string& getText() const { return m_text; }
std::string getText() const { return m_text; }
Font *getFont() const { return m_font; }
int getTextPos(Point pos);

@ -34,40 +34,44 @@ void registerLuaFunctions()
{
// App
g_lua.registerModule("App");
g_lua.registerMemberFunction("App", "exit", &lua_App_exit);
g_lua.registerMemberFunction("App", "setOnClose", &lua_App_setOnClose);
g_lua.registerMemberFunction("exit", &lua_App_exit);
// UI
g_lua.registerModule("UI");
g_lua.registerMemberFunction("UI", "load", &lua_UI_load);
g_lua.registerMemberFunction("UI", "getRootContainer", &lua_UI_getRootContainer);
g_lua.registerClass("UI");
g_lua.registerMemberFunction("load", &lua_UI_load);
g_lua.registerMemberFunction("getRootContainer", &lua_UI_getRootContainer);
// UILayout
g_lua.registerClass("UILayout");
// UIElement
g_lua.registerClass("UIElement", "UILayout");
g_lua.registerMemberField("UIElement", "onLoad", NULL, &lua_UIElement_setOnLoad);
g_lua.registerMemberField("UIElement", "onDestroy", NULL, &lua_UIElement_setOnDestroy);
g_lua.registerMemberField("UIElement", "parent", &lua_UIElement_getParent);
g_lua.registerMemberFunction("UIElement", "destroy", &lua_UIElement_destroy);
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("UIContainer", "getChildById", &lua_UIContainer_getChildById);
g_lua.registerMemberField("UIContainer", "locked", NULL, &lua_UIContainer_setLocked);
g_lua.registerMemberFunction("child", &lua_UIContainer_getChild);
g_lua.registerMemberFunction("children", &lua_UIContainer_getChildren);
// UILabel
g_lua.registerClass("UILabel", "UIElement");
g_lua.registerMemberField("UILabel", "text", &lua_UILabel_getText, &lua_UILabel_setText);
g_lua.registerMemberField("text", &lua_UILabel_getText, &lua_UILabel_setText);
// UIButton
g_lua.registerClass("UIButton", "UIElement");
g_lua.registerMemberField("UIButton", "onClick", NULL, &lua_UIButton_setOnClick);
// UITextEdit
g_lua.registerClass("UITextEdit", "UIElement");
// UIWindow
g_lua.registerClass("UIWindow", "UIContainer");
g_lua.registerMemberField("UIWindow", "title", &lua_UIWindow_getTitle, &lua_UIWindow_setTitle);
g_lua.registerMemberField("title", &lua_UIWindow_getTitle, &lua_UIWindow_setTitle);
}
@ -80,12 +84,6 @@ int lua_App_exit()
return 1;
}
int lua_App_setOnClose()
{
g_engine.setOnClose(g_lua.createSimpleFuncCallback(g_lua.popFunction()));
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UI module
@ -122,63 +120,92 @@ int lua_UI_getRootContainer()
////////////////////////////////////////////////////////////////////////////////
// UIElement
int lua_UIElement_setOnLoad()
int lua_UIElement_getId()
{
g_lua.insert(-2);
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance())) {
int funcRef = g_lua.popFunction();
element->associateLuaRef("onLoad", funcRef);
element->setOnLoad(g_lua.createScriptableSelfFuncCallback(funcRef));
} else
g_lua.pop();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushString(element->getId());
else
g_lua.pushNil();
return 1;
}
int lua_UIElement_setOnDestroy()
int lua_UIElement_setId()
{
g_lua.insert(-2);
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance())) {
int funcRef = g_lua.popFunction();
element->associateLuaRef("onDestroy", funcRef);
element->setOnDestroy(g_lua.createScriptableSelfFuncCallback(funcRef));
}
std::string id = g_lua.popString();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setId(id);
return 1;
}
int lua_UIElement_isEnabled()
{
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushBoolean(element->isEnabled());
else
g_lua.pop();
g_lua.pushNil();
return 1;
}
int lua_UIElement_getParent()
int lua_UIElement_setEnabled()
{
bool enabled = g_lua.popBoolean();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushClassInstance(element->getParent());
element->setEnabled(enabled);
return 1;
}
int lua_UIElement_isVisible()
{
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushBoolean(element->isVisible());
else
g_lua.pushNil();
return 1;
}
int lua_UIElement_destroy()
int lua_UIElement_setVisible()
{
bool visible = g_lua.popBoolean();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->destroy();
g_dispatcher.addTask(boost::bind(&LuaScript::collectGarbage, &g_lua));
element->setVisible(visible);
return 1;
}
int lua_UIElement_isFocused()
{
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushBoolean(element->isFocused());
else
g_lua.pushNil();
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UIContainer
int lua_UIElement_setFocused()
{
bool focused = g_lua.popBoolean();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->setFocused(focused);
return 1;
}
int lua_UIContainer_getChildById()
int lua_UIElement_getParent()
{
std::string id = g_lua.popString();
if(UIContainerPtr container = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance()))
g_lua.pushClassInstance(container->getChildById(id));
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
g_lua.pushClassInstance(element->getParent());
else
g_lua.pushNil();
return 1;
}
int lua_UIContainer_setLocked()
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;
}
int lua_UIElement_setLocked()
{
bool locked = g_lua.popBoolean();
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance())) {
@ -194,6 +221,42 @@ int lua_UIContainer_setLocked()
return 1;
}
int lua_UIElement_destroy()
{
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->destroy();
g_dispatcher.addTask(boost::bind(&LuaScript::collectGarbage, &g_lua));
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UIContainer
int lua_UIContainer_getChild()
{
std::string id = g_lua.popString();
if(UIContainerPtr container = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance()))
g_lua.pushClassInstance(container->getChildById(id));
else
g_lua.pushNil();
return 1;
}
int lua_UIContainer_getChildren()
{
if(UIContainerPtr container = boost::dynamic_pointer_cast<UIContainer>(g_lua.popClassInstance())) {
g_lua.newTable();
foreach(const UIElementPtr& child, container->getChildren()) {
g_lua.pushClassInstance(child);
if(child->getId().length())
g_lua.setField(child->getId());
}
} else
g_lua.pushNil();
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UILabel
@ -214,23 +277,6 @@ int lua_UILabel_getText()
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UIButton
int lua_UIButton_setOnClick()
{
g_lua.insert(-2);
if(UIButtonPtr button = boost::dynamic_pointer_cast<UIButton>(g_lua.popClassInstance())) {
int funcRef = g_lua.popFunction();
button->associateLuaRef("onClick", funcRef);
button->setOnClick(g_lua.createScriptableSelfFuncCallback(funcRef));
} else
g_lua.pop();
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// UIWindow

@ -30,29 +30,39 @@
void registerLuaFunctions();
// global functions
// App
int lua_App_exit();
int lua_App_setOnClose();
// UI
int lua_UI_load();
int lua_UI_getRootContainer();
// UIElement
int lua_UIElement_setOnLoad();
int lua_UIElement_setOnDestroy();
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_getChildById();
int lua_UIContainer_setLocked();
int lua_UIContainer_getChild();
int lua_UIContainer_getChildren();
// UILabel
int lua_UILabel_setText();
int lua_UILabel_getText();
// UIButton
int lua_UIButton_setOnClick();
void lua_UIButton_onClick();
// UIWindow
int lua_UIWindow_setTitle();

@ -26,6 +26,7 @@
#include <script/luascript.h>
#include <script/luafunctions.h>
#include <core/resources.h>
#include <lua.hpp>
LuaScript g_lua;
@ -82,6 +83,7 @@ bool LuaScript::loadBuffer(const std::string& text, const std::string& what)
// check if is loaded as a function
if(lua_isfunction(L, -1) == 0) {
pop();
return false;
}
@ -95,20 +97,20 @@ bool LuaScript::loadBuffer(const std::string& text, const std::string& what)
return true;
}
int LuaScript::loadBufferAsFunction(const std::string& text, const std::string& what)
bool LuaScript::loadBufferAsFunction(const std::string& text, const std::string& what)
{
int ret = luaL_loadbuffer(L, text.c_str(), text.length(), what.c_str());
if(ret != 0){
reportError(popString());
return LUA_REFNIL;
return false;
}
// check if is loaded as a function
if(lua_isfunction(L, -1) == 0) {
return LUA_REFNIL;
if(!isFunction()) {
pop();
return false;
}
return popFunction();
return true;
}
void LuaScript::reportError(const std::string& errorDesc, const char *funcName)
@ -117,7 +119,7 @@ void LuaScript::reportError(const std::string& errorDesc, const char *funcName)
ss << "LUA Script ERROR: ";
if(funcName)
ss << " in " << funcName << "(): ";
ss << errorDesc << std::endl;
ss << errorDesc;
logError(ss.str());
}
@ -144,19 +146,156 @@ void LuaScript::insert(int index)
lua_insert(L, index);
}
int LuaScript::ref()
void LuaScript::remove(int index)
{
return luaL_ref(L, LUA_REGISTRYINDEX);
lua_remove(L, index);
}
void LuaScript::unref(int ref)
void LuaScript::releaseRef(int ref)
{
luaL_unref(L, LUA_REGISTRYINDEX, ref);
}
void LuaScript::getRef(int ref)
void LuaScript::newTable()
{
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
lua_newtable(L);
}
void LuaScript::setTable(int index)
{
lua_settable(L, index);
}
void *LuaScript::newUserdata(int size)
{
return lua_newuserdata(L, size);
}
void LuaScript::newMetatable(const std::string& name)
{
luaL_newmetatable(L, name.c_str());
}
void LuaScript::setMetatable(const std::string& name, int index)
{
luaL_getmetatable(L, name.c_str());
if(isNil())
reportError(f("could not retrive metatable %d", name));
else
lua_setmetatable(L, index < 0 ? index-1 : index);
}
void LuaScript::rawGet(const std::string& key)
{
pushString(key);
lua_rawget(L, -2);
}
void LuaScript::rawSet(const std::string& key)
{
pushString(key);
insert(-2);
lua_rawset(L, -3);
}
void LuaScript::getField(const std::string& key)
{
lua_getfield(L, -1, key.c_str());
}
void LuaScript::setField(const std::string& key)
{
lua_setfield(L, -2, key.c_str());
}
void LuaScript::getScriptableField(const ScriptablePtr& scriptable, const std::string& field)
{
if(scriptable) {
pushRef(scriptable->getLuaTableRef());
getField(field);
remove(-2);
} else
pushNil();
}
void LuaScript::setScriptableField(const ScriptablePtr& scriptable, const std::string& field)
{
if(scriptable) {
pushRef(scriptable->getLuaTableRef());
insert(-2);
setField(field);
}
pop();
}
void LuaScript::rawGetGlobalTableField(const std::string& globalTable, const std::string& key)
{
getGlobal(globalTable);
rawGet(key);
remove(-2);
}
void LuaScript::rawSetGlobalTableField(const std::string& globalTable, const std::string& key)
{
getGlobal(globalTable);
insert(-2);
rawSet(key);
pop();
}
void LuaScript::getGlobal(const std::string& key)
{
lua_getfield(L, LUA_GLOBALSINDEX, key.c_str());
}
void LuaScript::setGlobal(const std::string& key)
{
lua_setfield(L, LUA_GLOBALSINDEX, key.c_str());
}
bool LuaScript::isNil(int index)
{
return lua_isnil(L, index);
}
bool LuaScript::isBoolean(int index)
{
return lua_isboolean(L, index);
}
bool LuaScript::isNumber(int index)
{
return lua_isnumber(L, index);
}
bool LuaScript::isString(int index)
{
return lua_isstring(L, index);
}
bool LuaScript::isTable(int index)
{
return lua_istable(L, index);
}
bool LuaScript::isUserdata(int index)
{
return lua_isuserdata(L, index);
}
bool LuaScript::isFunction(int index)
{
return lua_isfunction(L, index);
}
bool LuaScript::isCFunction(int index)
{
return lua_iscfunction(L, index);
}
bool LuaScript::isLuaFunction(int index)
{
return isFunction(index) && !isCFunction(index);
}
void LuaScript::pop(int n)
@ -171,7 +310,7 @@ bool LuaScript::popBoolean()
return b;
}
int32_t LuaScript::popInteger()
int LuaScript::popInteger()
{
double d = lua_tonumber(L, -1);
pop();
@ -187,6 +326,24 @@ std::string LuaScript::popString()
return str;
}
ScriptablePtr LuaScript::popClassInstance()
{
ScriptablePtr object;
if(isUserdata()) { // instances are store as userdata
object = *((ScriptablePtr *)lua_touserdata(L, -1));
if(!object)
reportErrorWithTraceback("attempt to retrive class instance from a object that is already expired");
} else if(!isNil()) // we accept nil values
reportErrorWithTraceback("couldn't retrive class instance, the value is not a scriptable type");
pop();
return object;
}
int LuaScript::popRef()
{
return luaL_ref(L, LUA_REGISTRYINDEX);
}
void LuaScript::pushNil()
{
lua_pushnil(L);
@ -207,55 +364,23 @@ void LuaScript::pushString(const std::string& str)
lua_pushstring(L, str.c_str());
}
void LuaScript::pushUserdata(void* ptr)
{
lua_pushlightuserdata(L, ptr);
}
void LuaScript::pushValue(int index)
{
lua_pushvalue(L, index);
}
void LuaScript::pushClassInstance(const ScriptablePtr& object)
{
if(object) {
// create weak_ptr to the scriptable object stored as userdata
new(lua_newuserdata(L, sizeof(ScriptablePtr))) ScriptablePtr(object);
// set object metatable
lua_getfield(L, LUA_REGISTRYINDEX, (std::string(object->getScriptableName()) + "_mt").c_str());
lua_setmetatable(L, -2);
} else {
lua_pushnil(L);
}
}
ScriptablePtr LuaScript::popClassInstance()
{
ScriptablePtr object;
if(lua_isuserdata(L, -1)) { // instances are store as userdata
object = *((ScriptablePtr *)lua_touserdata(L, -1));
if(!object)
reportErrorWithTraceback("attempt to retrive class instance from a object that is already expired");
} else if(!lua_isnil(L, -1)) // we accept nil values
reportErrorWithTraceback("couldn't retrive class instance, the value is not a scriptable type");
lua_pop(L, 1);
return object;
}
void LuaScript::pushFunction(int functionRef)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, functionRef);
new(newUserdata(sizeof(ScriptablePtr))) ScriptablePtr(object);
setMetatable(std::string(object->getScriptableName()) + "_mt");
} else
pushNil();
}
int LuaScript::popFunction()
void LuaScript::pushValue(int index)
{
return ref();
lua_pushvalue(L, index);
}
void LuaScript::releaseFunction(int functionRef)
void LuaScript::pushRef(int ref)
{
unref(functionRef);
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
}
void LuaScript::callFunction(int numArgs)
@ -277,53 +402,33 @@ void LuaScript::callFunction(int numArgs)
reportError("stack size changed!");
}
SimpleCallback LuaScript::createSimpleFuncCallback(int funcRef)
void LuaScript::callModuleField(const std::string& module, const std::string& field)
{
return [this, funcRef]() {
pushFunction(funcRef);
callFunction();
};
}
boost::function<void(ScriptablePtr)> LuaScript::createScriptableSelfFuncCallback(int funcRef)
{
return [this, funcRef](ScriptablePtr scriptable) {
pushClassInstance(scriptable);
setGlobal("self");
pushFunction(funcRef);
callFunction();
pushNil();
setGlobal("self");
};
}
void LuaScript::setGlobal(const char *varName)
{
lua_setfield(L, LUA_GLOBALSINDEX, varName);
g_lua.rawGetGlobalTableField(module, field);
g_lua.callFunction();
}
void LuaScript::setupPackageLoader()
{
lua_getfield(L, LUA_GLOBALSINDEX, "package");
lua_getfield(L, -1, "loaders");
lua_remove(L, -2);
lua_pushnil(L);
lua_getfield(L, LUA_GLOBALSINDEX, "package"); // package
lua_getfield(L, -1, "loaders"); // package.loaders, package
lua_remove(L, -2); // package.loaders
lua_pushnil(L); // nil, package.loaders
int numLoaders = 0;
while(lua_next(L, -2) != 0) {
lua_pop(L, 1);
// value, key, package.loaders
lua_pop(L, 1); // key, package.loaders
numLoaders++;
}
lua_pushinteger(L, numLoaders + 1);
lua_pushcfunction(L, &LuaScript::luaPackageLoader);
lua_rawset(L, -3);
lua_pop(L, 1);
lua_pushinteger(L, numLoaders + 1); // at, package.loaders
lua_pushcfunction(L, &LuaScript::luaPackageLoader); // luaPackageLoader, at, package.loaders
lua_rawset(L, -3); // package.loaders
lua_pop(L, 1); // (empty)
}
void LuaScript::registerClass(const std::string& klass, const std::string& baseClass)
{
// klass_mt = {}
// mt = {}
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, (klass + "_mt").c_str());
@ -344,35 +449,60 @@ void LuaScript::registerClass(const std::string& klass, const std::string& baseC
lua_pushcfunction(L, &LuaScript::luaGarbageCollectMetaMethod);
lua_setfield(L, -2, "__gc");
// klass_mt.methods = { }
// klass = { }
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setfield(L, LUA_GLOBALSINDEX, klass.c_str());
// mt.methods = klass
lua_setfield(L, -2, "methods");
// klass_mt.fieldmethods = { }
// klass_fieldmethods = { }
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setfield(L, LUA_GLOBALSINDEX, (klass + "_fieldmethods").c_str());
// mt.fieldmethods = klass_fieldmethods
lua_setfield(L, -2, "fieldmethods");
if(baseClass.length()) {
// klass_mt.base = baseClass_mt
lua_getfield(L, LUA_REGISTRYINDEX, (baseClass + "_mt").c_str());
lua_setfield(L, -2, "base");
// get klass
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);
lua_pop(L, 1);
// get klass_fieldmethods
lua_getfield(L, LUA_GLOBALSINDEX, (klass + "_fieldmethods").c_str());
// redirect = { __index = baseClass_fieldmethods }
lua_newtable(L);
lua_getfield(L, LUA_GLOBALSINDEX, (baseClass + "_fieldmethods").c_str());
lua_setfield(L, -2, "__index");
// setmetatable(klass_fieldmethods, redirect)
lua_setmetatable(L, -2);
}
lua_pop(L, 1);
m_currentClass = klass;
}
void LuaScript::registerMemberField(const std::string& klass, const std::string& field, LuaScript::LuaCFunction getFunction, LuaScript::LuaCFunction setFunction)
void LuaScript::registerMemberField(const std::string& field, LuaScript::LuaCFunction getFunction, LuaScript::LuaCFunction setFunction)
{
if(getFunction) {
int functionId = m_functions.size();
m_functions.push_back(getFunction);
// push the class table
lua_getfield(L, LUA_GLOBALSINDEX, (klass + "_fieldmethods").c_str());
lua_getfield(L, LUA_GLOBALSINDEX, (m_currentClass + "_fieldmethods").c_str());
// push the function id
lua_pushnumber(L, functionId);
// store id in the closure
@ -388,7 +518,7 @@ void LuaScript::registerMemberField(const std::string& klass, const std::string&
m_functions.push_back(setFunction);
// push the class table
lua_getfield(L, LUA_GLOBALSINDEX, (klass + "_fieldmethods").c_str());
lua_getfield(L, LUA_GLOBALSINDEX, (m_currentClass + "_fieldmethods").c_str());
// push the function id
lua_pushnumber(L, functionId);
// store id in the closure
@ -400,13 +530,13 @@ void LuaScript::registerMemberField(const std::string& klass, const std::string&
}
}
void LuaScript::registerMemberFunction(const std::string& klass, const std::string& functionName, LuaCFunction function)
void LuaScript::registerMemberFunction(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());
lua_getfield(L, LUA_GLOBALSINDEX, m_currentClass.c_str());
// push the function id
lua_pushnumber(L, functionId);
// store id in the closure
@ -432,9 +562,11 @@ void LuaScript::registerGlobalFunction(const std::string& functionName, LuaCFunc
void LuaScript::registerModule(const std::string& module)
{
// module = {}
lua_newtable(L); // module table
lua_setfield(L, LUA_GLOBALSINDEX, module.c_str()); // register at globals index
registerClass(module);
lua_getfield(L, LUA_GLOBALSINDEX, module.c_str());
lua_getfield(L, LUA_REGISTRYINDEX, (module + "_mt").c_str());
lua_setmetatable(L, -2);
lua_pop(L, -1);
}
int LuaScript::luaPackageLoader(lua_State* L)
@ -452,50 +584,52 @@ int LuaScript::luaPackageLoader(lua_State* L)
int LuaScript::luaIndexMetaMethod(lua_State* L)
{
// stack: key, obj
std::string key = lua_tostring(L, -1); // key, obj
lua_pop(L, 1); // obj
lua_getmetatable(L, -1); // mt, obj
while(!lua_isnil(L, -1)) {
lua_getfield(L, -1, "fieldmethods"); // mt.fieldmethods, mt, obj
lua_getfield(L, -1, ("get_" + key).c_str()); // mt.fieldmethods[get_key], mt.fieldmethods, mt, obj
lua_remove(L, -2); // mt.fieldmethods[get_key], mt, obj
lua_getfield(L, -1, "fieldmethods"); // fieldmethods, mt, obj
lua_getfield(L, -1, ("get_" + key).c_str()); // get_method, fieldmethods, mt, obj
lua_remove(L, -2); // get_method, mt, obj
if(!lua_isnil(L, -1)) {
lua_remove(L, -2); // get_method, obj
lua_insert(L, -2); // obj, get_method
lua_pushcfunction(L, &LuaScript::luaErrorHandler); // errorfunc, obj,get_method
lua_insert(L, -3); // obj, get_method, errorfunc
int ret = lua_pcall(L, 1, 1, -3); // ret, errorfunc
if(ret != 0) {
g_lua.reportError(g_lua.popString()); // errofunc
lua_pop(L, 1); // (empty)
lua_pushnil(L); // nil
} else {
lua_remove(L, -2); // ret
}
return 1;
} else {
lua_pop(L, 1); // mt, obj
lua_getfield(L, -1, "methods"); // methods, mt, obj
lua_getfield(L, -1, key.c_str()); // method, methods, mt, obj
lua_remove(L, -2); // method, mt, obj
if(!lua_isnil(L, -1)) {
lua_remove(L, -2); // mt.fieldmethods[get_key], obj
lua_insert(L, -2); // obj, mt.fieldmethods[get_key]
lua_pushcfunction(L, &LuaScript::luaErrorHandler); // errorfunc, obj, mt.fieldmethods[get_key]
lua_insert(L, -3); // obj, mt.fieldmethods[get_key], errorfunc
int ret = lua_pcall(L, 1, 1, -3); // ret, errorfunc
if(ret != 0) {
g_lua.reportError(g_lua.popString()); // errofunc
lua_pop(L, 1); // (empty)
lua_pushnil(L); // nil
} else {
lua_remove(L, -2); // ret
}
lua_insert(L, -3); // obj, mt, method
lua_pop(L, 2); // method
return 1;
} else {
lua_pop(L, 1); // mt, obj
lua_getfield(L, -1, "methods"); // mt.methods, mt, obj
lua_getfield(L, -1, key.c_str()); // mt.methods[key], mt.methods, mt, obj
lua_remove(L, -2); // mt.methods[key], mt, obj
if(!lua_isnil(L, -1)) {
lua_insert(L, -3);
lua_pop(L, 2);
return 1;
}
lua_pop(L, 1);
}
lua_getfield(L, -1, "base"); // mt.base, mt, obj
lua_remove(L, -2); // mt.base, obj
lua_pop(L, 1); // mt, obj
}
lua_pop(L, 1);
lua_pop(L, 1); // obj
ScriptablePtr scriptable = g_lua.popClassInstance();
int refId = scriptable->getLuaRef(key);
if(refId != -1)
g_lua.getRef(refId);
else
// stack: obj
if(g_lua.isTable()) {
g_lua.rawGet(key);
g_lua.remove(-2);
} else if(g_lua.isUserdata()) {
g_lua.getScriptableField(g_lua.popClassInstance(), key);
} else {
g_lua.pop();
g_lua.pushNil();
g_lua.reportErrorWithTraceback("unknown type in newindex metamethod");
}
return 1;
}
@ -503,39 +637,38 @@ int LuaScript::luaIndexMetaMethod(lua_State* L)
int LuaScript::luaNewIndexMetaMethod(lua_State* L)
{
// stack: value, key, obj
lua_insert(L, -2);
lua_insert(L, -2); // key, value, obj
std::string key = lua_tostring(L, -1);
lua_pop(L, 1);
lua_getmetatable(L, -2);
// stack: mt, value, obj
while(!lua_isnil(L, -1)) {
lua_getfield(L, -1, "fieldmethods");
lua_getfield(L, -1, ("set_" + key).c_str());
lua_remove(L, -2); // stack: set method, mt, value, obj
if(!lua_isnil(L, -1)) {
lua_remove(L, -2); // mt.fieldmethods[get_key], value, obj
lua_insert(L, -3); // value, obj, mt.fieldmethods[get_key]
lua_pushcfunction(L, &LuaScript::luaErrorHandler); // errorfunc, value, obj, mt.fieldmethods[get_key]
lua_insert(L, -4); // value, obj, mt.fieldmethods[get_key], errorfunc
int ret = lua_pcall(L, 2, 0, -4); // errorfunc
if(ret != 0)
g_lua.reportError(g_lua.popString()); // errofunc
lua_pop(L, 1);
return 1;
}
lua_pop(L, 1); // mt, value, obj
lua_getfield(L, -1, "base"); // mt.base, mt, value, obj
lua_remove(L, -2); // mt.base, value, obj
lua_pop(L, 1); // value, obj
lua_getmetatable(L, -2); // mt, value, obj
lua_getfield(L, -1, "fieldmethods"); // fieldmethods, mt, value, obj
lua_getfield(L, -1, ("set_" + key).c_str()); // set_method, fieldmethods, mt, value, obj
lua_remove(L, -2); // set_method, mt, value, obj
if(!lua_isnil(L, -1)) {
lua_remove(L, -2); // set_method, value, obj
lua_insert(L, -3); // value, obj, set_method
lua_pushcfunction(L, &LuaScript::luaErrorHandler); // errorfunc, value, obj, set_method
lua_insert(L, -4); // value, obj, set_method, errorfunc
int ret = lua_pcall(L, 2, 0, -4); // errorfunc
if(ret != 0)
g_lua.reportError(g_lua.popString()); // errofunc
lua_pop(L, 1); // (empty)
return 1;
}
lua_pop(L, 2); // mt, value, obj
// stack: value, obj
g_lua.insert(-2);
if(g_lua.isTable()) {
g_lua.insert(-2);
g_lua.rawSet(key);
g_lua.pop();
} else if(g_lua.isUserdata()) {
g_lua.setScriptableField(g_lua.popClassInstance(), key);
} else {
g_lua.pop(2);
g_lua.reportErrorWithTraceback("unknown type in index metamethod");
}
// stack:
g_lua.pop(); // value, obj
g_lua.insert(-2); // obj, value
ScriptablePtr scriptable = g_lua.popClassInstance();
g_lua.pushValue(); // value, value
int refId = g_lua.ref();
scriptable->associateLuaRef(key, refId);
g_lua.pop();
return 1;
}
@ -559,8 +692,10 @@ int LuaScript::luaEqualMetaMethod(lua_State* L)
int LuaScript::luaGarbageCollectMetaMethod(lua_State* L)
{
ScriptablePtr *objectRef = (ScriptablePtr *)lua_touserdata(L, -1);
objectRef->reset();
if(lua_isuserdata(L, -1)) {
ScriptablePtr *objectRef = (ScriptablePtr *)lua_touserdata(L, -1);
objectRef->reset();
}
lua_pop(L, 1);
return 1;
}

@ -27,11 +27,12 @@
#include <prerequisites.h>
#include <script/scriptable.h>
#include <lua.hpp>
#define reportFuncError(a) reportError(a, __FUNCTION__)
#define reportFuncErrorWithTraceback(a) reportErrorWithTraceback(a, __FUNCTION__)
struct lua_State;
class LuaScript
{
public:
@ -41,49 +42,73 @@ public:
void loadAllModules();
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");
bool loadBufferAsFunction(const std::string& text, const std::string& what = "luaBuffer");
void reportError(const std::string& errorDesc, const char *funcName = NULL);
void reportErrorWithTraceback(const std::string& errorDesc, const char *funcName = NULL);
void collectGarbage();
int getStackSize();
void insert(int index);
void remove(int index);
void releaseRef(int ref);
void newTable();
void setTable(int index = -3);
void *newUserdata(int size);
void newMetatable(const std::string& name);
void setMetatable(const std::string& name, int index = -1);
void rawGet(const std::string& key);
void rawSet(const std::string& key);
void getField(const std::string& key);
void setField(const std::string& key);
int ref();
void unref(int ref);
void getRef(int ref);
void getScriptableField(const ScriptablePtr& scriptable, const std::string& field);
void setScriptableField(const ScriptablePtr& scriptable, const std::string& field);
void rawGetGlobalTableField(const std::string& globalTable, const std::string& key);
void rawSetGlobalTableField(const std::string& globalTable, const std::string& key);
void getGlobal(const std::string& key);
void setGlobal(const std::string& key);
bool isNil(int index = -1);
bool isBoolean(int index = -1);
bool isNumber(int index = -1);
bool isString(int index = -1);
bool isTable(int index = -1);
bool isUserdata(int index = -1);
bool isFunction(int index = -1);
bool isCFunction(int index = -1);
bool isLuaFunction(int index = -1);
void pop(int n = 1);
bool popBoolean();
int popInteger();
std::string popString();
ScriptablePtr popClassInstance();
int popRef();
void pushNil();
void pushBoolean(bool b);
void pushInteger(int i);
void pushString(const std::string& str);
void pushUserdata(void* ptr);
void pushClassInstance(const ScriptablePtr& object);
void pushValue(int index = -1);
void pushRef(int ref);
void pop(int n = 1);
bool popBoolean();
int32_t popInteger();
std::string popString();
void pushFunction(int functionRef);
int popFunction();
void releaseFunction(int functionRef);
void callFunction(int numArgs = 0);
SimpleCallback createSimpleFuncCallback(int funcRef);
boost::function<void(ScriptablePtr)> createScriptableSelfFuncCallback(int funcRef);
void setGlobal(const char *varName);
void pushClassInstance(const ScriptablePtr& object);
ScriptablePtr popClassInstance();
void callModuleField(const std::string& module, const std::string& field);
typedef int (*LuaCFunction)();
void setupPackageLoader();
void registerClass(const std::string& klass, const std::string& baseClass = "");
void registerMemberField(const std::string& klass, const std::string& field, LuaCFunction getFunction, LuaCFunction setFunction = NULL);
void registerMemberFunction(const std::string& klass, const std::string& functionName, LuaCFunction function);
void registerMemberField(const std::string& field, LuaCFunction getFunction, LuaCFunction setFunction = NULL);
void registerMemberFunction(const std::string& functionName, LuaCFunction function);
void registerGlobalFunction(const std::string& functionName, LuaCFunction function);
void registerModule(const std::string& module);
@ -99,6 +124,7 @@ public:
private:
std::vector<LuaCFunction> m_functions;
std::string m_currentClass;
lua_State *L;
};

@ -27,25 +27,34 @@
#include <script/luascript.h>
#include <core/dispatcher.h>
void Scriptable::associateLuaRef(const std::string& refName, int refId)
int Scriptable::getLuaTableRef()
{
// check if there is already a ref with this name
if(m_luaRefs.find(refName) != m_luaRefs.end())
g_lua.unref(m_luaRefs[refName]);
m_luaRefs[refName] = refId;
if(m_luaTableRef == -1) {
g_lua.newTable();
m_luaTableRef = g_lua.popRef();
}
return m_luaTableRef;
}
int Scriptable::getLuaRef(const std::string& refName)
void Scriptable::releaseLuaTableRef()
{
if(m_luaRefs.find(refName) != m_luaRefs.end())
return m_luaRefs[refName];
return -1;
if(m_luaTableRef != -1) {
g_lua.releaseRef(m_luaTableRef);
m_luaTableRef = -1;
}
}
void Scriptable::clearLuaRefs()
void Scriptable::callLuaTableField(const std::string& field)
{
foreach(auto pair, m_luaRefs) {
g_lua.unref(pair.second);
}
m_luaRefs.clear();
g_lua.pushClassInstance(shared_from_this());
g_lua.setGlobal("self");
g_lua.getScriptableField(shared_from_this(), field);
if(g_lua.isFunction())
g_lua.callFunction();
else
g_lua.pop();
g_lua.pushNil();
g_lua.setGlobal("self");
}

@ -30,14 +30,16 @@
class Scriptable : public boost::enable_shared_from_this<Scriptable>
{
public:
Scriptable() : m_luaTableRef(-1) { }
virtual const char *getScriptableName() const { return NULL; }
void associateLuaRef(const std::string& refName, int refId);
int getLuaRef(const std::string& refName);
void clearLuaRefs();
int getLuaTableRef();
void releaseLuaTableRef();
void callLuaTableField(const std::string& field);
private:
std::map<std::string, int> m_luaRefs;
int m_luaTableRef;
};
typedef boost::shared_ptr<Scriptable> ScriptablePtr;

@ -33,8 +33,7 @@ void UIButton::onInputEvent(const InputEvent& event)
} else if(event.type == EV_MOUSE_LUP && m_state == UI::ButtonDown) {
m_state = UI::ButtonUp;
if(getRect().contains(event.mousePos)) {
if(m_onClickCallback)
g_dispatcher.addTask(boost::bind(m_onClickCallback, asUIElement()));
g_dispatcher.addTask(boost::bind(&Scriptable::callLuaTableField, shared_from_this(), "onClick"));
}
}
}

@ -42,18 +42,15 @@ public:
void onInputEvent(const InputEvent& event);
void setText(const std::string& text) { m_text = text; }
const std::string& getText() const { return m_text; }
std::string getText() const { return m_text; }
UI::EButtonState getState() { return m_state; }
void setOnClick(const UIElementCallback& callback) { m_onClickCallback = callback; }
virtual const char *getScriptableName() const { return "UIButton"; }
private:
std::string m_text;
UI::EButtonState m_state;
UIElementCallback m_onClickCallback;
};
#endif // UIBUTTON_H

@ -54,13 +54,14 @@ UIContainerPtr& UIContainer::getRoot()
return rootContainer;
}
void UIContainer::addChild(UIElementPtr child)
void UIContainer::addChild(const UIElementPtr& child)
{
m_children.push_back(child);
child->setParent(asUIContainer());
if(child->getParent() != asUIContainer())
child->setParent(asUIContainer());
}
void UIContainer::removeChild(UIElementPtr child)
void UIContainer::removeChild(const UIElementPtr& child)
{
// defocus if needed
if(m_focusedElement == child)
@ -72,8 +73,16 @@ void UIContainer::removeChild(UIElementPtr child)
// remove from children list
m_children.remove(child);
// child must have this container as parent
child->setParent(UIContainerPtr());
if(child->getParent() == asUIContainer())
child->setParent(UIContainerPtr());
}
bool UIContainer::hasChild(const UIElementPtr& child)
{
auto it = std::find(m_children.begin(), m_children.end(), child);
if(it != m_children.end())
return true;
return false;
}
UIElementPtr UIContainer::getChildById(const std::string& id)
@ -201,19 +210,15 @@ void UIContainer::focusNextElement()
setFocusedElement(element);
}
void UIContainer::setFocusedElement(UIElementPtr focusedElement)
void UIContainer::setFocusedElement(const UIElementPtr& focusedElement)
{
if(focusedElement != m_focusedElement) {
if(m_focusedElement) {
m_focusedElement->setFocused(false);
if(m_focusedElement)
m_focusedElement->onFocusChange();
}
m_focusedElement = focusedElement;
if(m_focusedElement) {
m_focusedElement->setFocused(true);
if(m_focusedElement)
m_focusedElement->onFocusChange();
}
}
// when containers are focused they go to the top
@ -222,7 +227,7 @@ void UIContainer::setFocusedElement(UIElementPtr focusedElement)
}
}
bool UIContainer::lockElement(UIElementPtr element)
bool UIContainer::lockElement(const UIElementPtr& element)
{
if(std::find(m_children.begin(), m_children.end(), element) != m_children.end()) {
m_lockedElements.remove(element);
@ -238,7 +243,7 @@ bool UIContainer::lockElement(UIElementPtr element)
return false;
}
bool UIContainer::unlockElement(UIElementPtr element)
bool UIContainer::unlockElement(const UIElementPtr& element)
{
auto it = std::find(m_lockedElements.begin(), m_lockedElements.end(), element);
if(it != m_lockedElements.end()) {

@ -40,29 +40,33 @@ public:
virtual void onInputEvent(const InputEvent& event);
/// Add an element, this must never be called from events loops
void addChild(UIElementPtr child);
void addChild(const UIElementPtr& child);
/// Remove an element, this must never be called from events loops
void removeChild(UIElementPtr child);
void removeChild(const UIElementPtr& child);
/// Check if has child
bool hasChild(const UIElementPtr& child);
/// Find an element in this container by id
UIElementPtr getChildById(const std::string& id);
/// Find an element by position
UIElementPtr getChildByPos(const Point& pos);
/// Find an element in this container and in its children by id
UIElementPtr recursiveGetChildById(const std::string& id);
/// Get children
const std::list<UIElementPtr>& getChildren() const { return m_children; }
/// Pushs a child to the top
void pushChildToTop(const UIElementPtr& child);
int getChildCount() const { return m_children.size(); }
/// Disable all children except the specified element
bool lockElement(UIElementPtr element);
bool lockElement(const UIElementPtr& element);
/// Renable all children
bool unlockElement(UIElementPtr element);
bool unlockElement(const UIElementPtr& element);
/// Focus next element
void focusNextElement();
/// Focus element
void setFocusedElement(UIElementPtr focusedElement);
void setFocusedElement(const UIElementPtr& focusedElement);
/// Get focused element
UIElementPtr getFocusedElement() const { return m_focusedElement; }

@ -34,8 +34,7 @@ UIElement::UIElement(UI::EElementType type) :
UILayout(),
m_type(type),
m_visible(true),
m_enabled(true),
m_focused(false)
m_enabled(true)
{
}
@ -56,8 +55,7 @@ void UIElement::internalOnDestroy()
//logTraceDebug(getId());
UIElementPtr me = asUIElement();
if(m_onDestroyCallback)
m_onDestroyCallback(me);
callLuaTableField("onDestroy");
// remove from parent
if(getParent()) {
@ -65,7 +63,7 @@ void UIElement::internalOnDestroy()
}
// free script stuff
clearLuaRefs();
releaseLuaTableRef();
g_dispatcher.addTask(boost::bind(&UIElement::internalDestroyCheck, asUIElement()));
}
@ -90,8 +88,7 @@ void UIElement::setSkin(const UIElementSkinPtr& skin)
void UIElement::onLoad()
{
if(m_onLoadCallback)
g_dispatcher.addTask(boost::bind(m_onLoadCallback, asUIElement()));
g_dispatcher.addTask(boost::bind(&Scriptable::callLuaTableField, shared_from_this(), "onLoad"));
}
void UIElement::render()
@ -139,3 +136,36 @@ void UIElement::moveTo(Point pos)
}
setRect(newRect);
}
void UIElement::setParent(UIContainerPtr parent)
{
UIElementPtr me = asUIElement();
UIContainerPtr oldParent = m_parent.lock();
m_parent.reset();
if(oldParent && oldParent->hasChild(me)) {
oldParent->removeChild(me);
}
if(parent) {
m_parent = UIContainerWeakPtr(parent);
if(!parent->hasChild(me))
parent->addChild(me);
}
}
bool UIElement::isFocused() const
{
if(UIContainerPtr parent = m_parent.lock())
return (parent->getFocusedElement() == shared_from_this());
return false;
}
void UIElement::setFocused(bool focused)
{
if(UIContainerPtr parent = m_parent.lock()) {
if(focused) {
parent->setFocusedElement(asUIElement());
} else if(parent->getFocusedElement() == asUIElement()) {
parent->setFocusedElement(UIElementPtr());
}
}
}

@ -67,9 +67,9 @@ public:
void moveTo(Point pos);
void setSkin(const UIElementSkinPtr& skin);
const UIElementSkinPtr& getSkin() const { return m_skin; }
UIElementSkinPtr getSkin() const { return m_skin; }
void setParent(UIContainerPtr parent) { m_parent = parent; }
void setParent(UIContainerPtr parent);
UIContainerPtr getParent() const { return m_parent.lock(); }
void setId(const std::string& id) { m_id = id; }
@ -78,8 +78,8 @@ public:
void setEnabled(bool enabled) { m_enabled = enabled; }
bool isEnabled() const { return m_enabled; }
void setFocused(bool focused) { m_focused = focused; }
bool isFocused() const { return m_focused; }
void setFocused(bool focused);
bool isFocused() const;
void setVisible(bool visible) { m_visible = visible; }
bool isVisible() const { return m_visible; }
@ -91,9 +91,6 @@ public:
virtual UIContainerPtr asUIContainer() { return UIContainerPtr(); }
virtual const char *getScriptableName() const { return "UIElement"; }
void setOnDestroy(const UIElementCallback& onDestroyCallback) { m_onDestroyCallback = onDestroyCallback; }
void setOnLoad(const UIElementCallback& onLoadCallback) { m_onLoadCallback = onLoadCallback; }
private:
UI::EElementType m_type;
UIContainerWeakPtr m_parent;
@ -101,9 +98,6 @@ private:
std::string m_id;
bool m_visible;
bool m_enabled;
bool m_focused;
UIElementCallback m_onLoadCallback;
UIElementCallback m_onDestroyCallback;
};
#endif // UIELEMENT_H

@ -38,7 +38,7 @@ public:
m_color(Color::white) { }
void setText(const std::string& text);
const std::string& getText() const { return m_text; }
std::string getText() const { return m_text; }
void setAlign(int align) { m_align = align; }
int getAlign() const { return m_align; }

@ -66,7 +66,7 @@ private:
class UILayout : public Scriptable
{
public:
UILayout() :
UILayout() : Scriptable(),
m_marginLeft(0),
m_marginRight(0),
m_marginTop(0),
@ -79,7 +79,7 @@ public:
/// Set the layout rect, always absolute position
void setRect(const Rect& rect);
/// Get layout size, it always return the absolute position
const Rect& getRect() const{ return m_rect; }
Rect getRect() const { return m_rect; }
// anchors add methods
bool addAnchor(EAnchorType type, const AnchorLine& anchorLine);

@ -215,23 +215,17 @@ void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
// load events
if(node.FindValue("onLoad")) {
const YAML::Node& cnode = node["onLoad"];
int funcRef = g_lua.loadBufferAsFunction(cnode.Read<std::string>(), element->getId() + ":onLoad");
if(funcRef != LUA_REFNIL) {
g_lua.pushClassInstance(element);
g_lua.pushFunction(funcRef);
lua_UIElement_setOnLoad();
} else
if(g_lua.loadBufferAsFunction(cnode.Read<std::string>(), element->getId() + ":onLoad"))
g_lua.setScriptableField(element, "onLoad");
else
logError(YAML::Exception(cnode.GetMark(), "failed to parse inline lua script").what());
}
if(node.FindValue("onDestroy")) {
const YAML::Node& cnode = node["onDestroy"];
int funcRef = g_lua.loadBufferAsFunction(cnode.Read<std::string>(), element->getId() + ":onDestroy");
if(funcRef != LUA_REFNIL) {
g_lua.pushClassInstance(element);
g_lua.pushFunction(funcRef);
lua_UIElement_setOnDestroy();
} else
if(g_lua.loadBufferAsFunction(cnode.Read<std::string>(), element->getId() + ":onDestroy"))
g_lua.setScriptableField(element, "onDestroy");
else
logError(YAML::Exception(cnode.GetMark(), "failed to parse inline lua script").what());
}
@ -314,13 +308,9 @@ void UILoader::loadButton(const UIButtonPtr& button, const YAML::Node& node)
// set on click event
if(node.FindValue("onClick")) {
int funcRef = g_lua.loadBufferAsFunction(node["onClick"].Read<std::string>(), button->getId() + ":onClick");
if(funcRef != LUA_REFNIL) {
g_lua.pushClassInstance(button);
g_lua.pushFunction(funcRef);
lua_UIButton_setOnClick();
} else {
if(g_lua.loadBufferAsFunction(node["onClick"].Read<std::string>(), button->getId() + ":onClick"))
g_lua.setScriptableField(button, "onClick");
else
logError(YAML::Exception(node["onClick"].GetMark(), "failed to parse inline lua script").what());
}
}
}

@ -41,7 +41,7 @@ public:
void onFocusChange();
void setText(const std::string& text);
const std::string& getText() const { return m_textArea.getText(); }
std::string getText() const { return m_textArea.getText(); }
TextArea& getTextArea() { return m_textArea; }
bool isFocusable() const { return true; }

@ -38,7 +38,7 @@ public:
void onInputEvent(const InputEvent& event);
void setTitle(const std::string& title) { m_title = title; }
const std::string& getTitle() const { return m_title; }
std::string getTitle() const { return m_title; }
virtual const char *getScriptableName() const { return "UIWindow"; }

Loading…
Cancel
Save