Lua event handlers always handle?
Posted: Thu Aug 07, 2008 10:08
I've noticed that whenever I add a Lua event handler, it always handles events, even if the event returns false. That is,
will handle all CharacterKey events, that is, they won't be passed further.
Is this intentional?
After some work, I found why this occurs, and how to patch CEGUI to change the behavior to one in which the return value is considered, as follows
The only changes to this function (in CEGUI/ScriptingModules/CEGUILua/LuaScriptModule/src/CEGUILuaFunctor.cpp) are changing 0 to 1 in the pcall (so a return value is expected), and then retrieving the result ('Kripken' appears near each one to point out the change). (Note that I have it raise an exception when there is no return value, as I like my events to always decide explicitly either way, but I guess it could return 'true' in that case, to keep the same behavior as before.)
Does this make sense, or am I not understanding something about CEGUI/Lua's approach to event handling?
Code: Select all
window:subscribeEvent("CharacterKey", function (args) return false end)
will handle all CharacterKey events, that is, they won't be passed further.
Is this intentional?
After some work, I found why this occurs, and how to patch CEGUI to change the behavior to one in which the return value is considered, as follows
Code: Select all
bool LuaFunctor::operator()(const EventArgs& args) const
{
// is this a late binding?
if (needs_lookup)
{
pushNamedFunction(L, function_name);
// reference function
index = luaL_ref(L, LUA_REGISTRYINDEX);
needs_lookup = false;
CEGUI_LOGINSANE("Late binding of callback '"+function_name+"' performed");
function_name.clear();
} // if (needs_lookup)
ScriptWindowHelper* helper = 0;
//Set a global for this window
if(args.d_hasWindow)
{
WindowEventArgs& we = (WindowEventArgs&)args;
helper = new ScriptWindowHelper(we.window);
tolua_pushusertype(L,(void*)helper,"CEGUI::ScriptWindowHelper");
lua_setglobal(L,"this");
}
// retrieve function
lua_rawgeti(L, LUA_REGISTRYINDEX, index);
// possibly self as well?
int nargs = 1;
if (self != LUA_NOREF)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, self);
++nargs;
}
// push EventArgs parameter
tolua_pushusertype(L, (void*)&args, "const CEGUI::EventArgs");
// call it
int error = lua_pcall(L, nargs, 1, 0); // Kripken: Add return value
// handle errors
if (error)
{
String errStr(lua_tostring(L, -1));
lua_pop(L, 1);
if(helper)
{
delete helper;
helper = 0;
}
throw ScriptException("Unable to call Lua event handler:\n\n"+errStr+"\n");
} // if (error)
// Kripken: retrieve result
bool ret;
if (lua_isboolean(L, -1))
ret = lua_toboolean(L, -1);
else
throw ScriptException("Lua script did not return a boolean\r\n");
lua_pop(L, 1);
if(helper)
{
delete helper;
helper = 0;
}
return ret;
}
The only changes to this function (in CEGUI/ScriptingModules/CEGUILua/LuaScriptModule/src/CEGUILuaFunctor.cpp) are changing 0 to 1 in the pcall (so a return value is expected), and then retrieving the result ('Kripken' appears near each one to point out the change). (Note that I have it raise an exception when there is no return value, as I like my events to always decide explicitly either way, but I guess it could return 'true' in that case, to keep the same behavior as before.)
Does this make sense, or am I not understanding something about CEGUI/Lua's approach to event handling?