Lua event handlers always handle?

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

kripken
Not too shy to talk
Not too shy to talk
Posts: 27
Joined: Mon Aug 04, 2008 10:05

Lua event handlers always handle?

Postby kripken » 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,

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?

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Postby CrazyEddie » Thu Aug 07, 2008 12:05

Hi,

First, thanks for the fix.

I'm not sure of mine and Lindquist's original intention with this, I can't see any reason why we would intentionally have it this way - so I guess it is a long standing omission of some kind.

I'll add a ticket to mantis and look into it further in a little while :)

CE.

kripken
Not too shy to talk
Not too shy to talk
Posts: 27
Joined: Mon Aug 04, 2008 10:05

Postby kripken » Thu Aug 07, 2008 12:19

CrazyEddie wrote:Hi,

First, thanks for the fix.

I'm not sure of mine and Lindquist's original intention with this, I can't see any reason why we would intentionally have it this way - so I guess it is a long standing omission of some kind.

I'll add a ticket to mantis and look into it further in a little while :)

CE.

Ok, I hope this turns out to be helpful :)

jtracy
Not too shy to talk
Not too shy to talk
Posts: 22
Joined: Wed Dec 20, 2006 17:20

Postby jtracy » Wed Oct 01, 2008 16:16

Looking at your code here it looks like you have a slight problem with your error handling. You are throwing before you pop the value from lua, so the stack will be corrupted if you do not return a boolean.

Code: Select all

 // 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;


I chose to implement it another way supporting the legacy code that I have that I did not want to update.

Code: Select all

    // Kripken: retrieve result
    bool ret = true; //if return is not a boolean handle it the same way as before
    if (lua_isboolean(L, -1)) {
        ret = lua_toboolean(L, -1);
    }
    lua_pop(L, 1);

   if(helper)
   {
      delete helper;
      helper = 0;
   }

    return ret;

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Postby CrazyEddie » Mon Oct 06, 2008 09:05

Hi,

Thanks for the alternate fixed-fix. I did not get around to doing this yet, so I did not introduce any issues into the CEGUI code (well, not related to this anyway :lol: )

CE.


Return to “Help”

Who is online

Users browsing this forum: Bing [Bot] and 14 guests