is no more redundant code; it is faster, uses less memory,
and will handle more possibilities than I had originally considered.
It was alot easier to test as well, as a single call will basically chain
through every part.
Here is the patch I added to my cegui 4
I didn't include an actual diff for 2 reasons:
1. I need to find a good diff program for windows.
2. I think I am the only one who will probably do this for version 4,
but once again, if its not in a newer version, I would like to see it.
This allows you to:
myWindow:subscribeEvent("Clicked","my:class:chain:to:the:function")
It also works with tolua (userdata) objects by doing the metatable
lookups.
CEGUILua.h - in the private: section
Code: Select all
/*! Takes away syntacitcal sugar. (!!Warning!!! will change the string you pass in!)*/
void lua_desugar(String &call_object);
/*! Pushes an argument list onto the stack...or just comma seperated variables.
\return
Number of variables processed (or parameters to a call).
*/
int Olua_pushvariables(lua_State *L,const char *args);
/*! Uses all methods to get at a table value for a pointer.
\return
Table index to use. (global or local)
*/
int Olua_pushtableof(lua_State *L,const char *ptr,int table_index);
/*! Pushes the value of any variable (global or member) onto the stack. */
void Olua_pushanyvariable(lua_State *L,const char *var);
/*! Pushes the value of any function (global or member), ready for a call. */
int Olua_pushanyfunction(lua_State *L,const char *var);
/*! Pushes any function, and self if need be onto the stack.
\return
Number of args generated (did it push self for you)
*/
int Olua_setupcall(lua_State *L,String call);
CEGUILua.cpp - the modified executeScriptedEvent
Code: Select all
bool LuaScriptModule::executeScriptedEventHandler(const String& handler_name, const EventArgs& e)
{
try
{
int nargs=Olua_setupcall(d_state,handler_name)+1;
// push EventArgs as the first parameter
tolua_pushusertype(d_state,(void*)&e,"const CEGUI::EventArgs");
// call it
int error = lua_pcall(d_state,nargs,0,0);
// handle errors
if ( error )
{
String msg = lua_tostring(d_state,-1);
lua_pop(d_state,1);
throw msg;
}
// return it
return true;
}
catch( const String& str )
{
lua_settop( d_state, 0 );
String msg = "(LuaScriptModule) Unable to execute scripted event handler: "+handler_name+"\n\n"+str+"\n";
throw GenericException( msg );
}
return false;
}
CEGUILua.cpp(same file) The function implementation additions.
Code: Select all
/** Takes away syntacitcal sugar. (!!Warning!!! will change the string you pass in!)*/
void LuaScriptModule::lua_desugar(String &call_object)
{
int pos;
//Take away any syntactical sugar
do {
pos=call_object.find(":");
if(pos!=String::npos)
call_object[pos]='.';
} while(pos!=String::npos);
}
/** Pushes an argument list onto the stack...or just comma seperated variables.
\return
Number of variables processed (or parameters to a call).
*/
int LuaScriptModule::Olua_pushvariables(lua_State *L,const char *args)
{
int pos,str_i;
String var;
String s_str(args);
int nargs=0;
if(s_str.length()) //Deal with each parameter
{
pos=-1;
while(pos != s_str.length())
{
str_i=pos+1;
pos=s_str.find(",",str_i);
if(pos==String::npos)
pos=s_str.length();
else
pos--;
//Pop off top of the list
var=s_str.substr(str_i,pos-str_i);
//Push the value of it on the stack
Olua_pushanyvariable(L,var.c_str());
nargs++;
}
}
return nargs;
}
/** Uses all methods to get at a table value for a pointer.
\return
Table index to use. (global or local)
*/
int LuaScriptModule::Olua_pushtableof(lua_State *L,const char *ptr,int table_index)
{
bool done=false;
int pos,error,nargs;
String name,params;
int ret_val=1; // Everyone but metamethods should return a ptr
String s_ptr(ptr);
while(!done)
{
pos=s_ptr.find("("); //If it is a function, keep the
if(pos==String::npos) //parameters out of the call.
pos=s_ptr.length();
//If this is empty, the value we need
//is already on the stack.
if(!s_ptr.empty())
{
name=s_ptr.substr(0,pos);
lua_pushstring(L,(const char *)name.c_str()); //Push this onto the stack
lua_gettable(L,table_index); //Get its value.
}
switch(lua_type(L,-1)) //Determine what type this is.
{
case LUA_TTABLE: //It is a table, we got what we needed.
if(table_index != LUA_GLOBALSINDEX) // Remove the old table.
lua_remove(L,table_index);
done=true;
table_index=-2;
break;
case LUA_TUSERDATA: //A C-ptr, probably has a metamethod.
if(!lua_getmetatable(L,-1))
throw(String("Syntax Error:"
+s_ptr
+" has no table."));
s_ptr="__index()"; //Now we just want this function's
table_index=-2; //return value.
ret_val=0; //Metamethods dont return anything :/
break;
case LUA_TFUNCTION:
params=s_ptr.substr(pos+1,
s_ptr.length()-pos-2);
nargs=Olua_pushvariables(L, //Push the parameters.
params.c_str());
error=lua_pcall(L,nargs,ret_val,0); //Call the function.
s_ptr="";
ret_val=1; //Make sure we reset this.
if(error)
throw(String("Parameters to "
+s_ptr+" are not valid."));
break;
default: //?No pointer?
throw(String
("Syntax Error: "
+s_ptr
+" is not a pointer to a known member."));
};
}
return table_index;
}
/** Pushes the value of any variable (global or member) onto the stack. */
void LuaScriptModule::Olua_pushanyvariable(lua_State *L,const char *var)
{
int str_i=0;
String token;
String call(var);
// Start at the global table.
int table_index=LUA_GLOBALSINDEX;
// Do one part at a time.
int pos=call.find(".",str_i);
while(pos != String::npos)
{
// Get a table value
token=call.substr(str_i,pos-str_i);
table_index=Olua_pushtableof(L,token.c_str(),table_index);
str_i=pos+1;
pos=call.find(".",str_i);
}
//Push the variable on the stack and get the variable value
token=call.substr(str_i);
lua_pushstring(L,token.c_str());
lua_gettable(L,table_index);
if(table_index != LUA_GLOBALSINDEX)
lua_remove(L,table_index);
}
/** Pushes the value of any function (global or member), ready for a call. */
int LuaScriptModule::Olua_pushanyfunction(lua_State *L,const char *var)
{
int str_i=0;
String token;
String call(var);
// Start at the global table.
int table_index=LUA_GLOBALSINDEX;
// Do one part at a time.
int pos=call.find(".",str_i);
while(pos != String::npos)
{
// Get a table value
token=call.substr(str_i,pos-str_i);
table_index=Olua_pushtableof(L,token.c_str(),table_index);
str_i=pos+1;
pos=call.find(".",str_i);
}
//Push the function on the stack and get the function value
token=call.substr(str_i);
lua_pushstring(L,token.c_str());
lua_gettable(L,table_index);
if(table_index != LUA_GLOBALSINDEX)
lua_remove(L,table_index);
//Don't push self.
if(table_index==LUA_GLOBALSINDEX)
return 0;
//Push self.
return 1;
}
/** Pushes any function, and self if need be onto the stack.
\return
Number of args generated (did it push self for you)
*/
int LuaScriptModule::Olua_setupcall(lua_State *L,String call)
{
String token;
int str_i=0;
// Get rid of syntactical sugar.
lua_desugar(call);
// Put the function on the stack.
int nargs=Olua_pushanyfunction(L,call.c_str());
// If this is a member call, push self
if(nargs)
{
token=call.substr(0,call.find_last_of("."));
Olua_pushvariables(L,token.c_str());
}
return nargs;
}
Anyway, hope someone else gets some use out of this.
Edit: To fix a problem with long calls.